Spring用了挺久的了,可是沒系統作過總結,恰好前段時間在作一個Spring封裝的項目,趁機回顧了下,便基於Spring framework 4.3.22作了源碼分析。git
剛開始接觸Spring時的入門例子大體以下:github
設置配置文件路徑,初始化ApplicationContext而後獲取Bean,處理完後關閉context便可。這一節先來了解Spring的啓動過程。web
跟蹤ClassPathXmlApplicationContext的構造方法能夠看到以下內容:spring
裏面設置了配置文件的路徑,而且調用了父類AbstractApplicationContext的refresh方法,該方法完成了Spring環境的初始化。以下,爲refresh方法的主要過程(爲方便排版,去除了原來的註釋和空格):segmentfault
下面將介紹各個方法步驟的內容,但不進行過多的深刻,後面會單獨對每一個深刻的細節進行詳細的介紹,這節先介紹大概過程。緩存
PrepareRefresh的內容如上,該方法主要進行環境的準備,包括Context的啓動時間,活動狀態,而後會設置context中的配置數據源,使用默認的StandardEnvironment對象,該對象添加了System.env()屬性和System.properties()屬性。initPropertySources方法用於初始化context 中 environment的屬性源。在AbstractApplicationContext中爲空實現。其餘子類的實現以下:服務器
對於GenericWebApplicationContext和AbstractRefreshableWebApplicationContext的實現大體一致,都是:session
經過在getEnvironment方法中,重寫createEnvironment方法,將默認的StandardEnvironment替換爲StandardServletEnvironment, Environment的關係圖爲:app
於是會執行該類的initPropertySources方法,爲context添加ServletContext和ServletConfig對應的配置屬性源。具體的Environment中配置屬性源的加載會在後面單獨進行介紹。編輯器
該方法的實現以下,經過refreshBeanFacotry重置AbstractApplicationContext持有的BeanFacotry,而後經過getBeanFacotry得到該對象再返回。
AbstractApplicationContext中refreshBeanFacoty方法和getBeanFactory方法都是抽象方法,具體實如今AbstractRefreshableApplicationContext上。
如上,增長了方法的註釋,重點在於loadBeanDefinitions方法,該抽象方法在具體實現子類上用於處理不一樣場景下Bean定義的加載,如Xml配置,註解配置,Web環境等,具體實現會在後面展開。
目前,只是完成了Bean定義的加載,沒有出現Bean的實例化。
爲第2步返回的BeanFactory設置基礎屬性。包括:
具體能夠看源碼,這步主要預先設置公共的單例Bean並添加一些公共的後置處理動做,主要體如今BeanPostProcessor上。
全部Bean的定義已經加載完成,可是沒有實例化,這一步能夠修改bean定義或者增長自定義的bean,AbstractApplicationContext中爲空實現。
如上,以AbstractRefreshableWebApplicationContext爲例,其增長了ServletContextAwareProcessor後置處理器,用於處理ServletContextAware接口和ServletConfigAware接口中相關對象的自動注入。同時新增了Web相關的應用範圍,包括:request,session,globalSession和application,並增長了各範圍默認的單例對象。最後增長了Web環境相關的環境配置Bean,包括servletContext,servletConfig,contextParameters和contextAttributes。
該步驟的功能同第3步相似,都可以增長一些後置處理器。
在Spring容器中找出實現了BeanFactoryPostProcessor接口的Bean並執行。Spring容器會委託給PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法執行,內容以下:
invokeBeanFactoryPostProcessors在處理時,將BeanFactoryPostProcessor分爲了兩類進行處理,BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,其中BeanDefinitionRegistryPostProcessor繼承自BeanFactoryPostProcessor。執行的時候,先找出全部的BeanDefinitionRegistryPostProcessor執行再找出全部BeanFactoryPostProcessor執行。由於BeanDefinitionRegistryPostProcessor繼承自BeanFactoryPostProcessor,因此執行後者時會過濾掉前者的內容。
在執行BeanDefinitionRegistryPostProcessor時,會按照以下的優先級,分類先執行postProcessBeanDefinitionRegistry方法,再統一執行全部的postProcessBeanFactory方法,,規則爲:
在執行BeanFactoryPostProcessor也會按照如上的規則,執行BeanFactoryPostProcessor方法。
這裏會實例化並初始化實現BeanFactoryPostProcessor接口的類並執行,若存在依賴的的Bean也會被初始化和實例化,具體的過程會在介紹Bean初始化過程時說明。
從Spring容器中找出的BeanPostProcessor接口的Bean,並添加到BeanFactory內部維護的List屬性中,以便後續Bean被實例化的時候調用這個BeanPostProcessor進行回調處理。該方法委託給了PostProcessorRegistrationDelegate類的registerBeanPostProcessors方法執行。執行過程同步驟5相似,也是按照優先級進行了篩選,具體順序爲:
其中MergedBeanDefinitionPostProcessor接口繼承自BeanPostProcessor接口,於是,上述第(4)點的列表同頭三點的列表是存在交集的。可是,AbstraceApplicationContext在添加BeanPostProcessor時,會先將存在的對象刪除,再添加新的,以下:
於是執行順序爲於是執行順序爲:PriorityOrdered、Ordered、NotOrdered、MergedBeanDefinitionPostProcessor。
這裏會實例化並初始化實現BeanPostProcessor接口的類,但不執行,若存在依賴的的Bean也會被初始化和實例化。
在Spring容器中初始化一些國際化相關的屬性
在Spring容器中初始化事件廣播器對象SimpleApplicationEventMulticaster,並將該對象做爲單例applicationEventMulticaster註冊到Context中。該廣播器用於廣播ApplicationEvent事件對應的ApplicationListener接口Bean。
PS:根據以上的順序,在這以前實例化的Bean,都不會通過BeanFactoryPostProcessor和BeanPostProcessor的處理,包括由於依賴而實例化的Bean,還有提早經過new註冊的Bean(只有直接調用BeanFactory.getBean方法獲取的bean纔會進行後置回調)。這裏須要注意,Context提早將兩種後置處理器的全部實現都提早加載了,因爲實例化前須要將依賴的Bean提早實例化,因此被這兩種後置處理器依賴的Bean的初始化動做,是不會被其監聽到的。
模板方法,可用於refresh動做的擴展,默認爲空實現。在SpringBoot中主要用於啓動內嵌的web服務器。
找出系統中的ApplicationListener對象,註冊到時間廣播器中。若是有須要提早進行廣播的時間,則執行廣播.
實例化BeanFactory中已經被註冊可是未實例化的全部實例(懶加載的不須要實例化),主要操做是BeanFacotry的preInstantiateSingletons方法。該方法分爲兩部分:
刷新後的其餘動做,包括:
銷燬全部已經註冊的單例,對於實現了DisposableBean的類,會先單獨進行銷燬,以便執行回調方法,再清理全部單例的緩存信息和剩餘的單例實例
將當前的活動狀態標識爲false
清除緩存
AbstractApplicationContext的close方法以下:
主要是調用doClose方法,而後判斷是否有shutdownHook,若是有則移除該鉤子,避免重複關閉,由於默認的shutdownHook也是調用的doClose方法。
doClose方法以下:
過程爲:
這兩個方法來自Lifecycle接口,以下,簡單的調用了DefaultLifecycleProcessor的start和stop方法,回調Lifecycle的實現類。
咱們知道Spring中存在不少預設的接口,用於擴展。經過以上分析,目前獲得的回調接口順序以下:
後續對其餘細節進行展開時,會看到更多的擴展接口,到時再更新上面的圖。
我的公衆號:啊駝