Spring:为什么“root”应用程序上下文和“servlet”应用程序上下文是由不同的各方创建的?

据我了解,基于Spring的Web应用程序初始化如下:

第1步Servlet container (eg Tomcat)定位ServletContainerInitializer的实现,它是SpringServletContainerInitializer

第2步SpringServletContainerInitializer创建DispatcherServletContextLoaderListener

第3步DispatcherServlet创建servlet application contextContextLoaderListener创建root application context

步骤1由Servlet 3.0规范定义。 第2,3步完全由Spring定义。

我可以看到将web bean放在servlet上下文non-web root non-web bean的合理性。 但是为什么我们必须在不同的地方创建这两个上下文,即DispatcherServletContextLoaderListener

如果我们只想准备一切必要的东西,为什么不在ContextLoaderListener创建两个上下文,因为它可以被看作整个Web应用程序的main()方法。 我认为这是更多的逻辑和当前的方法只会使事情复杂化。

添加1

根据@ Shailendra的回复,我画了这个:

在此处输入图像描述

我的理解是,Spring引入了application context概念并将它们存储在Servlet Context 。 Servlet Context是java servlet technolgoy引入的概念。

我想DispatcherServlet实现应该有一个成员变量来保存servlet application contextservlet application contextkey 。 所以它可以访问它自己的上下文。 也许关键是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 。 它从FrameworkServletinheritance了以下memeber:

 /** WebApplicationContext for this servlet */ private WebApplicationContext webApplicationContext; 

 public FrameworkServlet(WebApplicationContext webApplicationContext) { this.webApplicationContext = webApplicationContext; } 

但是为什么我们必须在不同的地方创建这两个上下文,即DispatcherServlet和ContextLoaderListener

因为两个上下文应该是不同的但是具有层次关系以便能够覆盖。 通常,使用ContextLoaderListener加载的上下文是属于整个应用程序的“root”上下文,而使用DispatcherServlet初始化的上下文实际上是特定于该servlet的。 从技术上讲,您可以在应用程序中拥有多个servlet,因此多个这样的上下文各自特定于相应的servlet但具有相同的根上下文。 有关详细信息,请参阅我的另一个答案。