Spring:为什么“root”应用程序上下文和“servlet”应用程序上下文是由不同的各方创建的?
据我了解,基于Spring的Web应用程序初始化如下:
第1步 : Servlet container (eg Tomcat)
定位ServletContainerInitializer
的实现,它是SpringServletContainerInitializer
。
第2步 : SpringServletContainerInitializer
创建DispatcherServlet
和ContextLoaderListener
第3步 : DispatcherServlet
创建servlet application context
。 ContextLoaderListener
创建root application context
。
步骤1由Servlet 3.0规范定义。 第2,3步完全由Spring定义。
我可以看到将web
bean放在servlet上下文和non-web
root non-web
bean的合理性。 但是为什么我们必须在不同的地方创建这两个上下文,即DispatcherServlet
和ContextLoaderListener
?
如果我们只想准备一切必要的东西,为什么不在ContextLoaderListener
创建两个上下文,因为它可以被看作整个Web应用程序的main()
方法。 我认为这是更多的逻辑和当前的方法只会使事情复杂化。
添加1
根据@ Shailendra的回复,我画了这个:
我的理解是,Spring引入了application context
概念并将它们存储在Servlet Context
。 Servlet Context是java servlet technolgoy引入的概念。
我想DispatcherServlet
实现应该有一个成员变量来保存servlet application context
中servlet application context
的key
。 所以它可以访问它自己的上下文。 也许关键是servlet名称。
root application context
应该有一个众所周知的密钥,以便每个人都可以访问它。
添加2
root application context
的众所周知的关键是:
(在org.springframework.web.context.WebApplicationContext
)
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
添加3
DispatcherServlet
确实引用了它的WebApplicationContext
。 它从FrameworkServlet
inheritance了以下memeber:
/** WebApplicationContext for this servlet */ private WebApplicationContext webApplicationContext;
和
public FrameworkServlet(WebApplicationContext webApplicationContext) { this.webApplicationContext = webApplicationContext; }
但是为什么我们必须在不同的地方创建这两个上下文,即DispatcherServlet和ContextLoaderListener
因为两个上下文应该是不同的但是具有层次关系以便能够覆盖。 通常,使用ContextLoaderListener
加载的上下文是属于整个应用程序的“root”上下文,而使用DispatcherServlet
初始化的上下文实际上是特定于该servlet的。 从技术上讲,您可以在应用程序中拥有多个servlet,因此多个这样的上下文各自特定于相应的servlet但具有相同的根上下文。 有关详细信息,请参阅我的另一个答案。