Spring: 为什么"root" application context 和"servlet" application context 是由不同方创建的?
Spring: Why "root" application context and "servlet" application context are created by different parties?
据我了解,基于 Spring 的 Web 应用程序初始化如下:
第1步:Servlet container (e.g. 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
个 bean 放在 root 上下文[=97= 中的合理性].但为什么我们必须在 不同的 位置创建这两个上下文,即 DispatcherServlet
和 ContextLoaderListener
?
如果全部我们想要的只是只是准备好所有必要的东西,为什么不直接创建ContextLoaderListener
中的两个上下文,因为它可以被视为整个 Web 应用程序的 main()
方法。我认为这更合乎逻辑,当前的方法只会使事情复杂化。
加 1
根据@Shailendra的回复,我画了这个:
我的理解是,Spring引入了application context
概念,并将它们存储在Servlet Context
中。 Servlet 上下文是 java servlet 技术引入的概念。
我想 DispatcherServlet
实现应该有一个成员变量来将 key
保存到 servlet context
中的 servlet application context
。所以它可以访问它自己的上下文。也许关键是 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
继承了以下成员:
/** WebApplicationContext for this servlet */
private WebApplicationContext webApplicationContext;
和
public FrameworkServlet(WebApplicationContext webApplicationContext) {
this.webApplicationContext = webApplicationContext;
}
But why do we have to create these 2 contexts in different places,
i.e. DispatcherServlet and ContextLoaderListener
因为这两个上下文应该是不同的,但具有层次关系以便能够覆盖。通常使用 ContextLoaderListener
加载的上下文是属于整个应用程序的 "root" 上下文,而使用 DispatcherServlet
初始化的上下文实际上特定于该 servlet。从技术上讲,您可以在一个应用程序中有多个 servlet,因此多个这样的上下文每个特定于各自的 servlet 但具有相同的根上下文。有关详细信息,请参阅我的另一个答案 here.
据我了解,基于 Spring 的 Web 应用程序初始化如下:
第1步:Servlet container (e.g. 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
个 bean 放在 root 上下文[=97= 中的合理性].但为什么我们必须在 不同的 位置创建这两个上下文,即 DispatcherServlet
和 ContextLoaderListener
?
如果全部我们想要的只是只是准备好所有必要的东西,为什么不直接创建ContextLoaderListener
中的两个上下文,因为它可以被视为整个 Web 应用程序的 main()
方法。我认为这更合乎逻辑,当前的方法只会使事情复杂化。
加 1
根据@Shailendra的回复,我画了这个:
我的理解是,Spring引入了application context
概念,并将它们存储在Servlet Context
中。 Servlet 上下文是 java servlet 技术引入的概念。
我想 DispatcherServlet
实现应该有一个成员变量来将 key
保存到 servlet context
中的 servlet application context
。所以它可以访问它自己的上下文。也许关键是 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
继承了以下成员:
/** WebApplicationContext for this servlet */
private WebApplicationContext webApplicationContext;
和
public FrameworkServlet(WebApplicationContext webApplicationContext) {
this.webApplicationContext = webApplicationContext;
}
But why do we have to create these 2 contexts in different places, i.e. DispatcherServlet and ContextLoaderListener
因为这两个上下文应该是不同的,但具有层次关系以便能够覆盖。通常使用 ContextLoaderListener
加载的上下文是属于整个应用程序的 "root" 上下文,而使用 DispatcherServlet
初始化的上下文实际上特定于该 servlet。从技术上讲,您可以在一个应用程序中有多个 servlet,因此多个这样的上下文每个特定于各自的 servlet 但具有相同的根上下文。有关详细信息,请参阅我的另一个答案 here.