Spring各种上下文的关系详解

       要想很好理解这三个上下文的关系,可以Debug追踪源码加深自己的理解。这对于解决出现的问题和需要仿写类似的框架提供了很多的思路。最近发现去品读源码,对于框架有了更深的理解和解决了做项目期间遗留的种种疑惑。

Spring的启动过程:

       首先,对于一个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 ApplicationContext

Interface 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 ServletContextAware beans and invoke the setServletContext method accordingly.

翻译:

公共接口WebApplicationContext
扩展ApplicationContext
提供Web应用程序配置的接口。 这在应用程序运行时是只读的,但是如果实现支持这个,可以重新加载。
该接口将一个getServletContext()方法添加到通用ApplicationContext接口,并定义一个众所周知的应用程序属性名称,该名称在引导进程中必须绑定根上下文。
像通用应用程序上下文一样,Web应用程序上下文是分层的。 每个应用程序都有一个根上下文,而应用程序中的每个servlet(包括MVC框架中的调度器servlet)都有自己的子上下文。
除了标准的应用程序上下文生命周期功能,WebApplicationContext实现还需要检测ServletContextAware bean,并相应地调用setServletContext方法。

发布了100 篇原创文章 · 获赞 300 · 访问量 68万+

猜你喜欢

转载自blog.csdn.net/win7system/article/details/91446098
今日推荐