要想很好理解这三个上下文的关系,可以Debug追踪源码加深自己的理解。这对于解决出现的问题和需要仿写类似的框架提供了很多的思路。最近发现去品读源码,对于框架有了更深的理解和解决了做项目期间遗留的种种疑惑。
首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;
其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;
再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是xmlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。
总结:
ServletContext: tomcat启动会创建一个ServletContext,作为全局上下文以及spring容器的宿主环境,可以理解为web容器(Servlet容器)
WebApplicationContext:即初始化根上下文(即IOC容器)
DispatcherServlet:WebApplicationContext设置为当前DispatcherServlet的父上下文。并且也把DispatcherServlet上下文存在ServletContext中
通过init方法创建的dispatcherServlet上下文可以访问通过ServletContextListener中创建的WebApplicationContext上下文中的bean,反之则不行。因为WebApplicationContext是dispatcherServlet上下文的父容器。
Spring API中的解释:
public interface WebApplicationContext
extends ApplicationContextInterface to provide configuration for a web application. This is read-only while the application is running, but may be reloaded if the implementation supports this.
This interface adds a
getServletContext()method to the generic ApplicationContext interface, and defines a well-known application attribute name that the root context must be bound to in the bootstrap process.Like generic application contexts, web application contexts are hierarchical. There is a single root context per application, while each servlet in the application (including a dispatcher servlet in the MVC framework) has its own child context.
In addition to standard application context lifecycle capabilities, WebApplicationContext implementations need to detect
ServletContextAwarebeans and invoke thesetServletContextmethod accordingly.
翻译:
公共接口WebApplicationContext
扩展ApplicationContext
提供Web应用程序配置的接口。 这在应用程序运行时是只读的,但是如果实现支持这个,可以重新加载。
该接口将一个getServletContext()方法添加到通用ApplicationContext接口,并定义一个众所周知的应用程序属性名称,该名称在引导进程中必须绑定根上下文。
像通用应用程序上下文一样,Web应用程序上下文是分层的。 每个应用程序都有一个根上下文,而应用程序中的每个servlet(包括MVC框架中的调度器servlet)都有自己的子上下文。
除了标准的应用程序上下文生命周期功能,WebApplicationContext实现还需要检测ServletContextAware bean,并相应地调用setServletContext方法。

本文详细阐述了Spring在Web应用中的启动过程,包括ServletContext作为全局上下文,WebApplicationContext作为Spring的IoC容器(根上下文),以及DispatcherServlet的初始化过程,它如何建立自己的IoC上下文并共享根上下文的bean。总结了ServletContext、WebApplicationContext和DispatcherServlet三者之间的关系。
1785

被折叠的 条评论
为什么被折叠?



