The relationship between DispacherServlet, WebApplicationContext, and ServletContext in Spring

Explanation one:

    To understand the relationship between these three contexts, you need to be familiar with how spring is started in the web container. The startup process of spring is actually the startup process of its IoC container. For web programs, the startup process of the IoC container is the process of establishing the context.

The startup process of spring:

  1. First of all, for a web application, it is deployed in the web container, and the web container provides a global context, which is the ServletContext, which provides the host environment for the subsequent spring IoC container;

  2. Secondly, contextLoaderListener will be provided in web.xml. When the web container starts, the container initialization event will be triggered. At this time, the contextLoaderListener will listen to this event, and its contextInitialized method will be called. In this method, spring will initialize a startup context, which is called the root context, namely WebApplicationContext , which is an interface class, to be precise, its actual implementation class is XmlWebApplicationContext. This is spring's IoC container, and the configuration of its corresponding bean definition is specified by the context-param tag in web.xml. After the IoC container is initialized, spring uses WebApplicationContext.ROOT WEB APPLICATION CONTEXT ATTRIBUTE as the attribute Key and stores it in the ServletContext for easy access;

  3. Once again, after the contextLoaderListener listener is initialized, it starts to initialize the Servlet configured in web.xml. This servlet can be configured with multiple ones. Take the most common DispatcherServlet as an example, this servlet is actually a standard front-end controller for forwarding, Match and process each servlet request. The DispatcherServlet context will establish its own IoC context during initialization to hold spring mvc-related beans. When establishing DispatcherServlet's own IoC context, it will use WebApplicationContext.ROOT WEB APPLICATION CONTEXT ATTRIBUTE to obtain the previous root context (ie WebApplicationContext) from ServletContext as the parent context of its own context. After you have this parent context, initialize the context you hold. The work of this DispatcherServlet to initialize its own context can be seen in its initStrategies method. The general work is to initialize processor mapping, view resolution, and so on. The default implementation class of the context held by this servlet is also mlWebApplicationContext. After initialization, spring uses the attribute related to the name of the servlet (here, it is not simply named as the servlet key, but through some conversion, you can view the source code by yourself) as the attribute key, and also save it in the ServletContext, so that subsequent use. In this way, each servlet holds its own context, that is, it has its own independent bean space, and each servlet shares the same beans, that is, those beans defined by the root context (the context initialized in step 2).

Explanation two:

    When configuring Spring in a web container (such as Tomcat), you may already be used to the following configuration code in the web.xml file:
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
                                                                                                                                             
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
                                                                                                                                             
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
                                                                                                                                         
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    以上配置首先会在ContextLoaderListener中通过<context-param>中的applicationContext.xml创建一个ApplicationContext,再将这个ApplicationContext塞到ServletContext里面,通过ServletContext的setAttribute方法达到此目的,在ContextLoaderListener的源代码中,我们可以看到这样的代码:

servletContext.setAttribute(
              WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
 this.context);

    以上由ContextLoaderListener创建的ApplicationContext是共享于整个Web应用程序的,而你可能早已经知道,DispatcherServlet会维持一个自己的ApplicationContext,默认会读取/WEB-INFO/<dispatcherServletName>-servlet.xml文件,而我么也可以重新配置:

<servlet>
    <servlet-name>
       customConfiguredDispacherServlet
   </servlet-name>
   <servlet-class>
       org.springframework.web.servlet.DispatcherServlet
   </servlet-class>
   <init-param>
       <param-name>
           contextConfigLocation
       </param-name>
       <param-value>
           /WEB-INF/dispacherServletContext.xml
       </param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
</servlet>

    问题是:以上两个ApplicationContext的关系是什么,它们的作用作用范围分别是什么,它们的用途分别是什么?

    ContextLoaderListener中创建ApplicationContext主要用于整个Web应用程序需要共享的一些组件,比如DAO,数据库的ConnectionFactory等。而由DispatcherServlet创建的ApplicationContext主要用于和该Servlet相关的一些组件,比如Controller、ViewResovler等。

    对于作用范围而言,在DispatcherServlet中可以引用由ContextLoaderListener所创建的ApplicationContext,而反过来不行。

    在Spring的具体实现上,这两个ApplicationContext都是通过ServletContext的setAttribute方法放到ServletContext中的。但是,ContextLoaderListener会先于DispatcherServlet创建ApplicationContext,DispatcherServlet在创建ApplicationContext时会先找到由ContextLoaderListener所创建的ApplicationContext,再将后者的ApplicationContext作为参数传给DispatcherServlet的ApplicationContext的setParent()方法,在Spring源代码中,你可以在FrameServlet.java中找到如下代码:

    wac.setParent(parent);

    其中,wac即为由DisptcherServlet创建的ApplicationContext,而parent则为有ContextLoaderListener创建的ApplicationContext。此后,框架又会调用ServletContext的setAttribute()方法将wac加入到ServletContext中。

    当Spring在执行ApplicationContext的getBean时,如果在自己context中找不到对应的bean,则会在父ApplicationContext中去找。这也解释了为什么我们可以在DispatcherServlet中获取到由ContextLoaderListener对应的ApplicationContext中的bean。

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.

http://www.cnblogs.com/snake-hand/p/3161372.html

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326602778&siteId=291194637