ContextLoaderListener容器初始化

来源:互联网 发布:慕尼黑工业大学 知乎 编辑:程序博客网 时间:2024/06/11 22:59

ContextLoaderListener容器初始化
http://blog.csdn.net/qq924862077/article/details/52769754

<context-param>      <param-name>contextConfigLocation</param-name>      <param-value>          classpath:applicationContext.xml      </param-value>  </context-param>  <listener>      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  </listener>  

在tomcat启动时,spring通过上述配置会初始化spring容器,注入applicationContext.xml中配置的bean以及其他一些配置。

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {    public ContextLoaderListener() {    }    public ContextLoaderListener(WebApplicationContext context) {        super(context);    }    @Override    public void contextInitialized(ServletContextEvent event) {        initWebApplicationContext(event.getServletContext());    }    @Override    public void contextDestroyed(ServletContextEvent event) {        closeWebApplicationContext(event.getServletContext());        ContextCleanupListener.cleanupAttributes(event.getServletContext());    }}

ContextLoderListener实现ServletContextListener接口,而该接口继承java的监听标记接口EventListener,表示当servlet容器启动时,就会接受通知,进而进行一系列的初始化操作。

public interface ServletContextListener extends EventListener {    /**     * Receives notification that the web application initialization     * process is starting.     *     * <p>All ServletContextListeners are notified of context     * initialization before any filters or servlets in the web     * application are initialized.     *     * @param sce the ServletContextEvent containing the ServletContext     * that is being initialized     */    public void contextInitialized(ServletContextEvent sce);    /**     * Receives notification that the ServletContext is about to be     * shut down.     *     * <p>All servlets and filters will have been destroyed before any     * ServletContextListeners are notified of context     * destruction.     *     * @param sce the ServletContextEvent containing the ServletContext     * that is being destroyed     */    public void contextDestroyed(ServletContextEvent sce);}

spring的具体初始化工作均在父类ContextLoder中进行,具体初始化步骤如下:

  1. 判断是否已经存在WebApplicationContext(spring容器),如果存在,则抛出异常。
  2. 创建WebApplicationContext容器,从web.xml中获取context-param名称为contextClass的value,该类必须实现WebApplicationContext接口,如果没有指定,则默认使用xmlWebApplicationContext。
  3. 判断创建的WebApplicationContext容器是否为ConfigurableApplicationContext的实例或子类,如果是,则判断该容器是否至少刷新一次并且还没有关闭(是否有效),如果无效,则重新设置容器的id,并加载对应的contextConfigLocation配置(spring配置),
    加载父容器,spring提供一个模板方法,如果需要配置父容器,可以继承ContextLoder,并覆盖loadParentContext方法。
  4. 线程绑定容器
/**     * Initialize Spring's web application context for the given servlet context,     * using the application context provided at construction time, or creating a new one     * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and     * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.     * @param servletContext current servlet context     * @return the new WebApplicationContext     * @see #ContextLoader(WebApplicationContext)     * @see #CONTEXT_CLASS_PARAM     * @see #CONFIG_LOCATION_PARAM     */    public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {        if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {            throw new IllegalStateException(                    "Cannot initialize context because there is already a root application context present - " +                    "check whether you have multiple ContextLoader* definitions in your web.xml!");        }        Log logger = LogFactory.getLog(ContextLoader.class);        servletContext.log("Initializing Spring root WebApplicationContext");        if (logger.isInfoEnabled()) {            logger.info("Root WebApplicationContext: initialization started");        }        long startTime = System.currentTimeMillis();        try {            // Store context in local instance variable, to guarantee that            // it is available on ServletContext shutdown.            if (this.context == null) {                //创建容器                this.context = createWebApplicationContext(servletContext);            }            if (this.context instanceof ConfigurableWebApplicationContext) {                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;                if (!cwac.isActive()) {                    // 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);                    }                    //如果容器无效,则重置contextId,且重新加载contextConfigLocation配置                    configureAndRefreshWebApplicationContext(cwac, servletContext);                }            }            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);            //线程绑定容器context            ClassLoader ccl = Thread.currentThread().getContextClassLoader();            if (ccl == ContextLoader.class.getClassLoader()) {                currentContext = this.context;            }            else if (ccl != null) {                currentContextPerThread.put(ccl, this.context);            }            if (logger.isDebugEnabled()) {                logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +                        WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");            }            if (logger.isInfoEnabled()) {                long elapsedTime = System.currentTimeMillis() - startTime;                logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");            }            return this.context;        }        catch (RuntimeException ex) {            logger.error("Context initialization failed", ex);            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);            throw ex;        }        catch (Error err) {            logger.error("Context initialization failed", err);            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);            throw err;        }    }
原创粉丝点击