Spring MVC source code analysis (a): Design and Implementation of ContextLoaderListener

ContextLoaderListener
in my Spring source code analysis (a): Where do you start to see the spring source of this article, analyzed in a web container, such as tomcat, start web application will pass the listener the way, notice ServletContextListener, web container started web applied, ServletContextListener can customize the initialization logic. ContextLoaderListener ServletContextListener is a class that implements the interface, mainly responsible for loading the spring main container-related bean, which is the default configuration information WEB-INF / applicationContext.xml file.


ContextLoaderListener ServletContextListener by implementing the interface, which will spring into the container web container. This can be understood in two angles:
web project itself: to receive notification web container web application is launched, start parsing loaded configure itself to create bean instance, to safeguard the main container spring projects related to the bean, and other components through a WebApplicationContext.
web container: web containers each ServletContext maintains a web application, ContextLoaderListener the spring container that WebApplicationContext, as an attribute ServletContext of, key is stored in the ServletContext, so the web container and spring items can interact through a ServletContext.
 
ContextLoaderListener only as an intermediate layer to establish a relationship spring containers and container web, the actual work is completed more than two angles is performed by ContextLoader, i.e. in ContextLoader defined above logic, the ContextLoaderListener implemented as follows:
package org.springframework.web.context;
**
 * Bootstrap listener to start up and shut down Spring's root {@link WebApplicationContext}.
 * Simply delegates to {@link ContextLoader} as well as to {@link ContextCleanupListener}.
 *
 * <p>As of Spring 3.1, {@code ContextLoaderListener} supports injecting the root web
 * application context via the {@link #ContextLoaderListener(WebApplicationContext)}
 * constructor, allowing for programmatic configuration in Servlet 3.0+ environments.
 * See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
 */
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    /**
     * Create a new {@code ContextLoaderListener} that will create a web application
     * context based on the "contextClass" and "contextConfigLocation" servlet
     * context-params. See {@link ContextLoader} superclass documentation for details on
     * default values for each.
     * <p>This constructor is typically used when declaring {@code ContextLoaderListener}
     * as a {@code <listener>} within {@code web.xml}, where a no-arg constructor is
     * required.
     * <p>The created application context will be registered into the ServletContext under
     * the attribute name {@link WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE}
     * and the Spring application context will be closed when the {@link #contextDestroyed}
     * lifecycle method is invoked on this listener.
     * @see ContextLoader
     * @see #ContextLoaderListener(WebApplicationContext)
     * @see #contextInitialized(ServletContextEvent)
     * @see #contextDestroyed(ServletContextEvent)
     */
    public ContextLoaderListener() {
    }
    /**
     * Create a new {@code ContextLoaderListener} with the given application context. This
     * constructor is useful in Servlet 3.0+ environments where instance-based
     * registration of listeners is possible through the {@link javax.servlet.ServletContext#addListener}
     * API.
     * <p>The context may or may not yet be {@linkplain
     * org.springframework.context.ConfigurableApplicationContext#refresh() refreshed}. If it
     * (a) is an implementation of {@link ConfigurableWebApplicationContext} and
     * (b) has <strong>not</strong> already been refreshed (the recommended approach),
     * then the following will occur:
     * <ul>
     * <li>If the given context has not already been assigned an {@linkplain
     * org.springframework.context.ConfigurableApplicationContext#setId id}, one will be assigned to it</li>
     * <li>{@code ServletContext} and {@code ServletConfig} objects will be delegated to
     * the application context</li>
     * <li>{@link #customizeContext} will be called</li>
     * <li>Any {@link org.springframework.context.ApplicationContextInitializer ApplicationContextInitializer org.springframework.context.ApplicationContextInitializer ApplicationContextInitializers}
     * specified through the "contextInitializerClasses" init-param will be applied.</li>
     * <li>{@link org.springframework.context.ConfigurableApplicationContext#refresh refresh()} will be called</li>
     * </ul>
     * If the context has already been refreshed or does not implement
     * {@code ConfigurableWebApplicationContext}, none of the above will occur under the
     * assumption that the user has performed these actions (or not) per his or her
     * specific needs.
     * <p>See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
     * <p>In any case, the given application context will be registered into the
     * ServletContext under the attribute name {@link
     * WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE} and the Spring
     * application context will be closed when the {@link #contextDestroyed} lifecycle
     * method is invoked on this listener.
     * @param context the application context to manage
     */
    public ContextLoaderListener(WebApplicationContext context) {
        super(context);
    }
    /**
     * Initialize the root web application context.
     */
    @Override
    public void contextInitialized(ServletContextEvent event) {
        initWebApplicationContext(event.getServletContext());
    }    
    /**
     * Close the root web application context.
     */
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        closeWebApplicationContext(event.getServletContext());
        ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }
}
ContextLoader
ContextLoader mainly responsible for loading the spring primary container that root ApplicationContext, at the design level mainly defined contextId, contextConfigLocation, contextClass, contextInitializerClasses. These parameters can be specified in the configuration, as the web.xml context-param tag, or the definition of the Java programming WebApplicationInitializer configuration mode based respectively as:
1.contextId: current id container, primarily to the underlying BeanFactory used, making use of the sequence.
 
2.contextConfigLocation: location profile, default WEB-INF / applicationContext.xml, can specify another location by using the web.xml context-param tag, or other names specify multiple separated by commas. In the configuration file to define bean as the main label by beans. Such underlying BeanFactory tag and resolves beans bean inside, thereby creating a collection BeanDefinitions, i.e. bean metadata database memory.
 
3.contextClass: WebApplicationContext type currently used, if it is specified in the beans WEB-INF / applicationContext.xml, then used as XmlWebApplicationContext, if by annotation, such as @ Configuration, @ Component, etc., are AnnotationConfigWebApplicationContext, by scanning basePackages specified package to create the bean.
 
4.contextInitializerClasses: ApplicationContextInitializer implementation class, before beanDefinition and create ApplicationContext bean that is loaded in the call of refresh, to WebApplicationContext some initialization.

initWebApplicationContext: Create and initialize a main spring corresponding container WebApplicationContext, complete two major actions:

1. Create WebApplicationContext object instance and invoke the refresh operation is completed from the specified configuration contextConfigLocation, load and create bean instances BeanDefinitions; source core to achieve the following:
// Store in local context instance variable, that to Guarantee Your
 // IT IS the Available ON the ServletContext the shutdown. 
IF ( the this the .context == null ) { 

   // create a the WebApplicationContext
    // specific type if it is specified using the specified contextClass ;
    // the XmlWebApplicationContext 
   
    the this .context = createWebApplicationContext (where servletContext); 
} 
IF ( the this .context the instanceof ConfigurableWebApplicationContext) { 
    ConfigurableWebApplicationContext CWAC = (ConfigurableWebApplicationContext) the this .context;
    if (!cwac.isActive()) {
    
        // 设置parent WebApplicationContext,
        // 对root WebApplicationContext来说,通常为null
        
        // The context has not yet been refreshed -> provide services such as
        // setting the parent context, setting the application context id, etc
        if (cwac.getParent() == null) {
            // The context instance was injected without an explicit parent ->
            // determine parent for root web application context, if any.
            ApplicationContext parent = loadParentContext(servletContext);
            cwac.setParent(parent);
        }
        
        // core methods, to complete the loading configuration, and defines the BeanDefinition bean objects created 
        configureAndRefreshWebApplicationContext (CWAC, where servletContext); 
    } 
}

configureAndRefreshWebApplicationContext main method to complete the set value ApplicationContext profile address contextConfigLocation, call the ApplicationContextInitializers, and finally call the refresh method of creating the ApplicationContext bean container.

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        
        ...
        
        wac.setServletContext(sc);
        String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
        if (configLocationParam != null) {
            wac.setConfigLocation(configLocationParam);
        }

        // The wac environment's #initPropertySources will be called in any case when the context
        // is refreshed; do it eagerly here to ensure servlet property sources are in place for
        //Processing in the any POST-use or that Occurs below Initialization Prior to #refresh 
        ConfigurableEnvironment the env = wac.getEnvironment ();
         IF (the env the instanceof ConfigurableWebEnvironment) { 
            ((ConfigurableWebEnvironment) the env) .initPropertySources (SC, null ); 
        } 
        // use ApplicationContextInitializer ApplicationContext to initialize 
        customizeContext (SC, WAC); 
        
        // ApplicationContext core method: start ApplicationContext complete refresh process in
         // i.e. the respective core components to create a spring containers, such as beanDefinitions, enviromnet etc. 
        
        wac.refresh (); 
    }

2. Create a good example as to create a good WebApplicationContext WebApplicationContext instance, as an attribute stored in the ServletContext among the core source code to achieve the following:

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

WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE which is:

    /**
     * Context attribute to bind root WebApplicationContext to on successful startup.
     * <p>Note: If the startup of the root context fails, this attribute can contain
     * an exception or error as value. Use WebApplicationContextUtils for convenient
     * lookup of the root WebApplicationContext.
     * @see org.springframework.web.context.support.WebApplicationContextUtils#getWebApplicationContext
     * @see org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext
     */
    String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
to sum up
Through the above analysis shows, ContextLoader spring to complete the creation of the main vessel, the work is responsible from the ServletContext, specifically from a web.xml file or WebApplicationInitializer ServletContext implementation class, gets WebApplicationContext relevant configuration information, such as the use contextClass specify which species WebApplicationContext achieve, contextConfigLocation specified spring container configuration files where and get WebApplicationContextInitializers to create a container before making spring of WebApplicationContext for reprocessing.
Created spring container, is the use of spring-context package ApplicationContext, BeanFactory spring-beans package, to complete the acquisition beans defined from the configuration and create the BeanDefinition, get some resource attribute value, and the completion of a single embodiment bean create the like. After the analysis of specific articles ApplicationContext and BeanFactory architecture in.
 
For more learning materials, can be added to the group: 473 984 645 or under the Fanger Wei code scanning

Guess you like

Origin www.cnblogs.com/1013wang/p/11763049.html