閱讀704 返回首頁    go 阿裏雲 go 技術社區[雲棲]


SpringMVC - ContextLoaderListener

我們在使用SpringMVC的時候,做的第一件事情是配置**ContextLoaderListener**的監聽器,這個監聽器的作用,就是啟動web容器的時候,自動裝配ApplicationContext的配置信息,因為ContextLoaderListener實現了ServletContextListener接口,便會將ApplicationContext放置到servletContext中。

Spring - ContextLoaderListener 的源碼解讀

/**
 * Initialize the root web application context
 */
@Override
public void contextInitialized(ServletContextEvent event) {
   super.initWebApplicationContext(event.getServletContext());
}
/**
 * Initialize Spring's web application context for the given servlet context, 
 */
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {

     //  判斷web.xml中存在多次ContextLoader定義
     if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
      throw new IllegalStateException( "....");
      }

     try {
      if (this.context == null) {
            // 初始化context (重點)
        this.context = createWebApplicationContext(servletContext);
       }

      if (this.context instanceof ConfigurableWebApplicationContext) {
         ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
        if (!cwac.isActive()) {
            if (cwac.getParent() == null) {
                ApplicationContext parent = loadParentContext(servletContext);
                cwac.setParent(parent);
              }
            configureAndRefreshWebApplicationContext(cwac, servletContext);
         }
        }

       // 將webApplicationContext放入到ServletContext中
       servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

       ClassLoader ccl = Thread.currentThread().getContextClassLoader();
       if (ccl == ContextLoader.class.getClassLoader()) {
         currentContext = this.context;
        }
        else if (ccl != null) {
        currentContextPerThread.put(ccl, this.context);
        }
             return this.context;
    }
        catch (RuntimeException ex) {

        }
    }
創建contextClass
這段代碼就是創建webApplicationContext的核心,當前類的ContextLoader同樣目錄下一定會存在屬性文件:ContextLoader.properties

**org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext**

然後通過反射的機製,進行實體類的創建

protected Class<?> determineContextClass(ServletContext servletContext) {
     String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
     if (contextClassName != null) {
       return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader()); 
      }  else {
       contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
       return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());   
      }
}

整個源碼跟蹤下來,可以簡單的歸納一下:
1. webApplicationContext存在性的驗證
2. 創建webApplicationContext實例
3. 將實例記錄在ServletContext中
4. 映射當前類加載器與創建的實例到全局變量中
private static final Map currentContextPerThread = new ConcurrentHashMap<>(1);)

最後更新:2017-08-22 19:02:15

  上一篇:go  移動端SDK優化的特點與經驗分享
  下一篇:go  新時代農產品收割 ,還有3D視覺科技加入