据我了解,基于 Spring 的 Web 应用程序初始化如下:
Step 1:Servlet容器(例如Tomcat)
定位到ServletContainerInitializer
的实现,即SpringServletContainerInitializer
。
第二步:SpringServletContainerInitializer
创建DispatcherServlet
和ContextLoaderListener
第 3 步:DispatcherServlet
创建 servlet 应用程序上下文
。 ContextLoaderListener
创建 root application context
。
第 1 步由 Servlet 3.0 规范定义。第 2、3 步完全由 Spring 定义。
我可以看到将 web
bean 放入 servlet 上下文 并将 non-web
bean 放入 root 上下文。但是为什么我们必须在不同的地方创建这两个上下文,即DispatcherServlet
和ContextLoaderListener
?
如果我们想要所有只是准备一切必要的,为什么不在ContextLoaderListener
中创建两个上下文因为它可以看作是整个 Web 应用程序的 main()
方法。我认为这更符合逻辑,而当前的方法只会使事情复杂化。
添加 1
根据@Shailendra 的回复,我画了这个:
我的理解是,Spring引入了application context
的概念,并将它们存储在Servlet Context
中。 Servlet Context是java servlet technolgoy引入的一个概念。
我猜 DispatcherServlet
实现应该有一个成员变量来将 key
保存到 servlet 上下文中的
。所以它可以访问它自己的上下文。也许关键是 servlet 名称。servlet 应用程序上下文
root application context
应该有一个 well-known 键,这样每个人都可以访问它。
添加 2
root application context
的 well-known 键是这样的:
(在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
加载的上下文是属于整个应用程序的“根”上下文,而使用 DispatcherServlet
初始化的上下文实际上特定于该 servlet。从技术上讲,您可以在一个应用程序中拥有多个 servlet,因此多个这样的上下文每个特定于各自的 servlet,但具有相同的根上下文。有关更多详细信息,请参阅我的另一个答案 here .
关于java - Spring:为什么 "root"应用上下文和 "servlet"应用上下文是不同方创建的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33163441/