spring-framework原始碼研讀

黃小數發表於2017-11-02

1.根據我們常用的web.xml裡,我們找到的org.springframework.web.context.ContextLoaderListener。web.xml如下


<?xml version="1.0" encoding="UTF-8"?>
<web-app
        version="3.0"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <display-name>moon</display-name>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener> 
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:applicationContext.xml
        </param-value>
    </context-param>
</web-app>
  1. 其實ContextLoaderListener是一個ServletContextListener,一個web容器的監聽器。根據其父類org.springframework.web.context.ContextLoader初始化的策略配置,找到類目錄下面的ContextLoader.properties檔案。裡面配置著一個Spring上下文類。
# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers.

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

額外知識點:
參考《ClassPathResource知識點》

  1. 載入策略資源(ContextLoader.properties)後,web容器啟動時會呼叫ContextLoaderListener的contextInitialized方法。
  2. contextInitialized方法裡初始化ContextLoader.properties配置的org.springframework.web.context.support.XmlWebApplicationContext,這個初始化過程有點長。
    4.1 從ServletContext獲取物件springcontext物件,如果存在則拋異常。key=org.springframework.web.context.WebApplicationContext.ROOT
    4.2 從ContextLoader.properties獲取className=org.springframework.web.context.support.XmlWebApplicationContext
    4.3 通過ClassUtils工具例項化spring的ApplicationContext,我們能夠看出他是使用ContextLoader類的類載入器,這裡有個可以弄個知識點《ClassUtils知識點》
ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader())

4.4 XmlWebApplicationContext例項化時,其一些列父類也將初始化和例項化(我稍微地簡化說,具體的可以看原始碼):

層次 類名 作用
第0層 org.springframework.web.context.support.XmlWebApplicationContext 定義預設配置檔案,如/WEB-INF/applicationContext.xml
第1層 org.springframework.web.context.support.AbstractRefreshableWebApplicationContext 宣告瞭ServletContext servletContext和ServletConfig servletConfig
第2層 org.springframework.context.support.AbstractRefreshableConfigApplicationContext 此時就跟web沒多大關係了,定義了配置變數String[] configLocations
第3層 org.springframework.context.support.AbstractRefreshableApplicationContext 此層就重要了,定義了DefaultListableBeanFactory beanFactory
第4層 org.springframework.context.support.AbstractApplicationContext 此層定義了父context,還有ApplicationContext的其他配置等,refresh()方法
第5層 org.springframework.core.io.DefaultResourceLoader 此層與ApplicationContext沒多大關係,從包名也能看出,宣告瞭ClassLoader
第6層(最後一層) org.springframework.core.io.ResourceLoader spring的作者的註釋是Strategy interface for loading resources,嗯哈,大概猜是使用策略模式的介面
  1. 例項化完XmlWebApplicationContext類後,就開始做點事情了。在ContextLoader裡,有個方法configureAndRefreshWebApplicationContext(cwac, servletContext),從方法名就能看出是配置和重新整理ApplicationContext。
    5.1 設定ServletContext,參考第1層
    5.2 設定configLocations,參考第2層,這裡又一個知識點《StringUtils知識點》
    5.3 呼叫AbstractRefreshableWebApplicationContext的createEnvironment()方法來初始化StandardServletEnvironment物件。參考知識點《StandardServletEnvironment知識點》
    5.4 呼叫StandardServletEnvironment物件initPropertySources(ServletContext servletContext, ServletConfig servletConfig)方法來獲取web容器所有配置資訊。配置資訊都在放在StandardServletEnvironment物件的MutablePropertySources物件裡。
    5.5 customizeContext(sc, wac)自定義初始化applicationContext的一些資訊,裡面是獲取實現org.springframework.context.ApplicationContextInitializer介面的一些方法呼叫。一個知識點也誕生《ApplicationContextInitializer知識點》

    5.6 重頭戲來了,refresh ApplicationContext!!!,呼叫第4層的refresh()方法。

      5.6.1 第一步:載入ServletContext和ServletConfig引數,並使用PropertySourcesPropertyResolver校驗是否有必須的配置缺失,可參考知識點《PropertySourcesPropertyResolver知識點》。
      
      5.6.2 第二步:例項化BeanFactory,交給子類AbstractRefreshableApplicationContext來例項化(參考第3層),例項化了org.springframework.beans.factory.support.DefaultListableBeanFactory物件作為變數beanFactory的值。並配置是否允許覆蓋bean和是否允許迴圈引用,預設都是否。
      
      
      5.6.3 第三步:第3層AbstractRefreshableApplicationContext去loadBeanDefinitions,loadBeanDefinitions方法被子類XmlWebApplicationContext覆寫了,建立org.springframework.beans.factory.xml.XmlBeanDefinitionReader物件進行載入Bean的定義。這個是重點核心的知識點,參考《XmlBeanDefinitionReader知識點》。  
       
      看到這裡應該知道每一層ApplicationContext的作用吧,一層一層往上遞進
      
      5.6.4 第四步: //TODO 正在研讀XmlBeanDefinitionReader
    
  2. //TODO

相關文章