spring源碼分析系列5:ApplicationContext的初始化與Bean生命周期
- 2019 年 10 月 17 日
- 筆記
回顧Bean與BeanDefinition的關係. BeanFactory容器. ApplicationContext上下文.
首先總結下:
- 開發人員定義Bean資訊:分為XML形式定義;註解式定義
- ApplicationContext搜集Bean的定義;存儲到BeabFactory容器的中。
- BeanFactory根據這些BeanDefinition創建Bean.快取起來供我們使用。
[開發人員]--標註-->[Bean定義] ---搜集 -->[BeanDefinition]---創建-->[Bean]
此節:我們從程式碼層面分析此過程.
refresh()
refresh()方法描述了ApplicationContext的初始化過程,這個過程大部分工作都是執行Bean定義到BeanDefinition到Bean的過程。
refresh()大致可以分為五部分來看:
1.BeanDefinition入庫前準備階段:
- prepareRefresh();:主要工作環境屬性的初始化,校驗。
- obtainFreshBeanFactory();: 準備一個beanFactory()(註:XML配置形式的Bean大多在此時執行了搜集入庫)
- prepareBeanFactory(beanFactory);:配置beanFactory的相關資訊,包括類載入;類載入器,解析器,需要的依賴和需要忽略的依賴,早期的Bean級別後處理器,創建環境相關Bean
- postProcessBeanFactory(beanFactory); 該方法只要是針對web類型的上下文中的增加配置beanFactory的相關屬性。
總的的來說,此階段是在做beanFactory的相關配置。
2.BeanDefinition搜集入庫階段:
- invokeBeanFactoryPostProcessors(beanFactory):此方法主要了搜集註解型BeanDefinition,註冊這些BeanDefinition, 執行BeanFactoryPostProcessor.postProcessBeanFactory()方法,做入庫時的修改操作。
此過程非常的精妙。由PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()全全負責,
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法上本質就幹了兩件事:
- 執行註冊型BeanFactoryPostProcessor:此時有個重要的ConfigurationClassPostProcessor註冊器,此類會將註解配置型的BeanDefinition找到,並註冊到BeanFactory中。
- 執行普通類型的BeanFactoryPostProcessor:做入庫的修改操作。
3.部分特殊功能的Bean提前創建:
此階段把少部分特殊用處的BeanDefinition先創建Bean供使用。
- registerBeanPostProcessors(beanFactory);實例化一些BeanPostProcessor為將來的BeanDefinition生成Bean時做準備。。
- initMessageSource(); 初始化ApplicationContext的國際化相關組件Bean,消息綁定,消息解析
- initApplicationEventMulticaster();:初始化廣播器組件Bean,用於初始化過程中廣播階段性事件。
- onRefresh(); 初始化子類中特殊Beans(也算是一個擴展點)
- registerListeners();:將容器中的監聽器Bean,設置到廣播器中去。
4.普通BeanDefinition生成Bean階段
此階段是大部分BeanDefinition生成Bean的階段。
finishBeanFactoryInitialization(beanFactory);:
此過程,就是上篇文章說的 ,applicationContext上下文觸發beanFactory內部的BeanDefinition創建Bean。我們想像一個場景: 先往一個機器內先放入原料BeanDefinition後,然後再按下開關開始製造.ApplicationContext在此處就好比按下開關.開始Bean的製造,Bean的製作過程是一條流水線,流水線上有不同類型的機器對原料做不同的處理,最終得到Bean
ApplicationContext調用DefaultListableBeanFactory.preInstantiateSingletons()開始觸發Bean的創建:
doGetBean:
- 首先檢查倉庫中是否已經創建過此Bean,有取出來
- 沒有就準備走流水線創建Bean創建.
- 創建前先檢查物料有沒有?有,標記當前Bean在創建中
- 檢查是否有依賴,有的話,先去載入創建依賴Bean. 又回到了1
- 判斷作用域,上createBean()流水線準備執行。
doGetBean->createBean:
- 載入Bean的Class類
- 驗證以及準備需要覆蓋的方法
doGetBean->createBean->代理對象: 返回代理對象
- 創建代理對象:給BeanPostProcessors 一個機會來返回代理對象來代替真正的實例(此處返回的是針對自定義TargetSource的Bean)
doGetBean->createBean->doCreateBean:沒有創建自定義代理對象繼續執行
- 使用合適的實例化策略來創建Bean(工廠方法、構造函數自動注入、簡單初始化),並得到Bean包裝類BeanWrapper對象。
- 調用BeanDefinitionPostProcessor後置處理器,修改 BeanDefinition
- 解決單例模式的循環依賴:解決辦法是儘早暴露Bean的引用到快取中,讓其他對象可以能引用到他
- populateBean設置bean的屬性
- initializeBean:
doGetBean->createBean->doCreateBean->initializeBean 實例化Bean
- invokeAwareMethods:執行_awre類型的方法
- applyBeanPostProcessorsBeforeInitialization執行BeanPostProcessor的前置方法
- invokeInitMethods: 執行InitializingBean介面的afterPropertiesSet ,invokeCustomInitMethod執行自定義的init-method方法
- applyBeanPostProcessorsAfterInitialization:執行BeanPostProcessor的後置方法
- 返回Bean. 至此BeanDefinition到Bean的生產過程完成。
5.applicationContext的收尾階段
finishRefresh();
收尾階段其實也算是applicationContext的擴展點。Lifecycle介面生命周期介面,(1.首先會從Bean容器中獲取LifecycleProcessor類型的Bean,如果沒有則創建一個默認的DefaultLifecycleProcessor。LifecycleProcessor是幹嘛用的?LifecycleProcessor是用來處理Lifecycle介面的bean的。
(2.使用獲得LifecycleProcessor執行實現了Lifecycle介面的Bean的start()方法
(3.發布上下文初始化完成事件
(4.Participate in LiveBeansView MBean, if active.不是很清楚幹嘛的。
Bean的生命周期
看完了refresh()方法。我們再來總結下Bean的生命周期。
用一張圖表示

Bean的完整生命周期分為四個階段:
第一階段:實例化階段。
從Bean定義的收集到BeanDefinition的入庫順序執行
BeanDefinitionRegistryPostProcessor註冊處理器,註冊一些BeanDefinition
BeanFactoryPostProcessor,對入庫的BeanDefinition進行定義的修改。
BeanWrapper的產生,BeanWrapper是Bean的早期產品。
populateBean()執行屬性的設置
總結:此階段是BeanDefinition->BeanWrapper ,各種屬性的設置第二階段:初始化階段:主要是執行各種初始化方法
invokeAwareMethods(beanName, bean);執行Aware屬性的相關設置。
BeanPostProcessor.postProcessBeforeInitialization前置方法的執行,
如果實現了InitializingBean.afterPropertiesSet()則執行此方法
執行自定義的initMethod方法。
BeanPostProcessor.postProcessBeforeInitialization後置方法的執行,第三階段:使用階段
getBean從容器的快取中取出Bean第四階段:銷毀階段
執行DisposableBean.distroy方法
執行自定義detry-method
總結:
整個spring初始化過程可以看做是
- 物料(BeanDefinition)的搜集入庫(BeanFactory)
- 生產線(getBean())取出物料創建成品(Bean)
- 成品(Bean)入庫(BeanFactory)
歡迎大家關注我的公眾號【源碼行動】,最新個人理解及時奉送。
