11張流程圖搞定Spring Bean生命周期
在網(wǎng)上已經(jīng)有跟多Bean的生命周期的博客,但是很多都是基于比較老的版本了,最近把整個流程化成了一個流程圖。待會兒使用流程圖,說明以及代碼的形式來說明整個聲明周期的流程。注意因為代碼比較多,這里的流程圖只畫出了大概的流程,具體的可以深入代碼。
一、獲取Bean
 第一階段獲取Bean
這里的流程圖的入口在 AbstractBeanFactory類的 doGetBean方法,這里可以配合前面的 getBean方法分析文章進行閱讀。主要流程就是
1、先處理Bean 的名稱,因為如果以“&”開頭的Bean名稱表示獲取的是對應(yīng)的FactoryBean對象;
2、從緩存中獲取單例Bean,有則進一步判斷這個Bean是不是在創(chuàng)建中,如果是的就等待創(chuàng)建完畢,否則直接返回這個Bean對象
3、如果不存在單例Bean緩存,則先進行循環(huán)依賴的解析
4、解析完畢之后先獲取父類BeanFactory,獲取到了則調(diào)用父類的getBean方法,不存在則先合并然后創(chuàng)建Bean
二、創(chuàng)建Bean
2.1 創(chuàng)建Bean之前

在真正創(chuàng)建Bean之前邏輯
這個流程圖對應(yīng)的代碼在 AbstractAutowireCapableBeanFactory類的 createBean方法中。
1、這里會先獲取 RootBeanDefinition對象中的Class對象并確保已經(jīng)關(guān)聯(lián)了要創(chuàng)建的Bean的Class 。
2、這里會檢查3個條件
(1)Bean的屬性中的 beforeInstantiationResolved字段是否為true,默認是false。
(2)Bean是原生的Bean
(3)Bean的 hasInstantiationAwareBeanPostProcessors屬性為true,這個屬性在Spring準(zhǔn)備刷新容器錢轉(zhuǎn)杯BeanPostProcessors的時候會設(shè)置,如果當(dāng)前Bean實現(xiàn)了 InstantiationAwareBeanPostProcessor則這個就會是true。
當(dāng)三個條件都存在的時候,就會調(diào)用實現(xiàn)的 InstantiationAwareBeanPostProcessor接口的 postProcessBeforeInstantiation方法,然后獲取返回的Bean,如果返回的Bean不是null還會調(diào)用實現(xiàn)的 BeanPostProcessor接口的 postProcessAfterInitialization方法,這里用代碼說明:
 3、如果上面3個條件其中一個不滿足就不會調(diào)用實現(xiàn)的方法。默認這里都不會調(diào)用的這些 BeanPostProcessors的實現(xiàn)方法。然后繼續(xù)執(zhí)行后面的 doCreateBean方法。
2.1 真正的創(chuàng)建Bean,doCreateBean

doCreateBean方法邏輯
這個代碼的實現(xiàn)還是在 AbstractAutowireCapableBeanFactory方法中。流程是
1、先檢查 instanceWrapper變量是不是null,這里一般是null,除非當(dāng)前正在創(chuàng)建的Bean在 factoryBeanInstanceCache中存在這個是保存還沒創(chuàng)建完成的FactoryBean的集合。
2、調(diào)用createBeanInstance方法實例化Bean,這個方法在后面會講解
3、如果當(dāng)前 RootBeanDefinition對象還沒有調(diào)用過實現(xiàn)了的 MergedBeanDefinitionPostProcessor接口的方法,則會進行調(diào)用 。
4、 當(dāng)滿足以下三點(1)是單例Bean(2)嘗試解析bean之間的循環(huán)引用(3)bean目前正在創(chuàng)建中則會進一步檢查是否實現(xiàn)了 SmartInstantiationAwareBeanPostProcessor接口如果實現(xiàn)了則調(diào)用是實現(xiàn)的 getEarlyBeanReference方法
5、 調(diào)用 populateBean方法進行屬性填充,這里后面會講解
6、 調(diào)用 initializeBean方法對Bean進行初始化,這里后面會講解
2.1.1 實例化Bean,createBeanInstance

實例化Bean
這里的邏輯稍微有一點復(fù)雜,這個流程圖已經(jīng)是簡化過后的了。簡要根據(jù)代碼說明一下流程:



1、先檢查Class是否已經(jīng)關(guān)聯(lián)了,并且對應(yīng)的修飾符是否是public的
2、如果用戶定義了Bean實例化的函數(shù),則調(diào)用并返回
3、如果當(dāng)前Bean實現(xiàn)了 FactoryBean接口則調(diào)用對應(yīng)的 FactoryBean接口的 getObject方法
4、根據(jù)getBean時候是否傳入構(gòu)造參數(shù)進行處理
4.1 如果沒有傳入構(gòu)造參數(shù),則檢查是否存在已經(jīng)緩存的無參構(gòu)造器,有則使用構(gòu)造器直接創(chuàng)建,沒有就會調(diào)用 instantiateBean方法先獲取實例化的策略默認是 CglibSubclassingInstantiationStrategy,然后實例化Bean。最后返回
4.2 如果傳入了構(gòu)造參數(shù),則會先檢查是否實現(xiàn)了 SmartInstantiationAwareBeanPostProcessor接口,如果實現(xiàn)了會調(diào)用 determineCandidateConstructors獲取返回的候選構(gòu)造器。
4.3 檢查4個條件是否滿足一個
(1)構(gòu)造器不為null,
(2)從RootBeanDefinition中獲取到的關(guān)聯(lián)的注入方式是構(gòu)造器注入(沒有構(gòu)造參數(shù)就是setter注入,有則是構(gòu)造器注入)
(3)含有構(gòu)造參數(shù)
(4)getBean方法傳入構(gòu)造參數(shù)不是空
滿足其中一個則會調(diào)用返回的候選構(gòu)造器實例化Bean并返回,如果都不滿足,則會根據(jù)構(gòu)造參數(shù)選擇合適的有參構(gòu)造器然后實例化Bean并返回
5、如果上面都沒有合適的構(gòu)造器,則直接使用無參構(gòu)造器創(chuàng)建并返回Bean。
2.1.2 填充Bean,populateBean

填充Bean
這里還是根據(jù)代碼來說一下流程



 
1、檢查當(dāng)前Bean是否實現(xiàn)了 InstantiationAwareBeanPostProcessor的 postProcessAfterInstantiation方法則調(diào)用,并結(jié)束Bean的填充。2、將按照類型跟按照名稱注入的Bean分開,如果注入的Bean還沒有實例化的這里會實例化,然后放到 PropertyValues對象中。3、如果實現(xiàn)了 InstantiationAwareBeanPostProcessor類的 postProcessProperties則調(diào)用這個方法并獲取返回值,如果返回值是null,則有可能是實現(xiàn)了過期的 postProcessPropertyValues方法,這里需要進一步調(diào)用 postProcessPropertyValues方法4、進行參數(shù)填充
2.1.3 初始化Bean,initializeBean

初始化Bean
同時這里根據(jù)代碼跟流程圖來說明
1、如果Bean實現(xiàn)了 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware則調(diào)用對應(yīng)實現(xiàn)的方法 。
2、Bean不為null并且bean不是合成的,如果實現(xiàn)了 BeanPostProcessor的 postProcessBeforeInitialization則會調(diào)用實現(xiàn)的 postProcessBeforeInitialization方法。在 ApplicationContextAwareProcessor類中實現(xiàn)了 postProcessBeforeInitialization方法。而這個類會在Spring刷新容器準(zhǔn)備 beanFactory的時候會加進去,這里就會被調(diào)用,而調(diào)用里面會檢查Bean是不是 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware的實現(xiàn)類。這里就會調(diào)用對應(yīng)的實現(xiàn)方法。代碼如下


1、實例化Bean然后,檢查是否實現(xiàn)了 InitializingBean的 afterPropertiesSet方法,如果實現(xiàn)了就會調(diào)用
2、Bean不為null并且bean不是合成的,如果實現(xiàn)了 BeanPostProcessor的 postProcessBeforeInitialization則會調(diào)用實現(xiàn)的 postProcessAfterInitialization方法。
到此創(chuàng)建Bean 的流程就沒了,剩下的就是容器銷毀的時候的了
三、destory方法跟銷毀Bean
Bean在創(chuàng)建完畢之后會檢查用戶是否指定了 destroyMethodName以及是否實現(xiàn)了 DestructionAwareBeanPostProcessor接口的 requiresDestruction方法,如果指定了會記錄下來保存在 DisposableBeanAdapter對象中并保存在bean的 disposableBeans屬性中。代碼在 AbstractBeanFactory的 registerDisposableBeanIfNecessary中


在銷毀Bean的時候最后都會調(diào)用 AbstractAutowireCapableBeanFactory的 destroyBean方法。

這里是創(chuàng)建一個 DisposableBeanAdapter對象,這個對象實現(xiàn)了Runnable接口,在實現(xiàn)的 run方法中會調(diào)用實現(xiàn)的 DisposableBean接口的 destroy方法。并且在創(chuàng)建 DisposableBeanAdapter對象的時候會根據(jù)傳入的bean是否實現(xiàn)了 DisposableBean接口來設(shè)置 invokeDisposableBean變量,這個變量表實有沒有實現(xiàn) DisposableBean接口



四、總結(jié)
最后來一個大的流程

實例化前的準(zhǔn)備階段

實例化前

實例化后

初始化前
















 
 
 








 
 
 
 