新聞中心
在網(wǎng)上已經(jīng)有跟多Bean的生命周期的博客,但是很多都是基于比較老的版本了,最近把整個流程化成了一個流程圖。待會兒使用流程圖,說明以及代碼的形式來說明整個聲明周期的流程。注意因?yàn)榇a比較多,這里的流程圖只畫出了大概的流程,具體的可以深入代碼。

創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括寧遠(yuǎn)網(wǎng)站建設(shè)、寧遠(yuǎn)網(wǎng)站制作、寧遠(yuǎn)網(wǎng)頁制作以及寧遠(yuǎn)網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,寧遠(yuǎn)網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到寧遠(yuǎn)省份的部分城市,未來相信會繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
一、獲取Bean
第一階段獲取Bean
這里的流程圖的入口在 AbstractBeanFactory類的 doGetBean方法,這里可以配合前面的 getBean方法分析文章進(jìn)行閱讀。主要流程就是
1、先處理Bean 的名稱,因?yàn)槿绻浴?”開頭的Bean名稱表示獲取的是對應(yīng)的FactoryBean對象;
2、從緩存中獲取單例Bean,有則進(jìn)一步判斷這個Bean是不是在創(chuàng)建中,如果是的就等待創(chuàng)建完畢,否則直接返回這個Bean對象
3、如果不存在單例Bean緩存,則先進(jìn)行循環(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,默認(rèn)是false。
(2)Bean是原生的Bean
(3)Bean的 hasInstantiationAwareBeanPostProcessors屬性為true,這個屬性在Spring準(zhǔn)備刷新容器錢轉(zhuǎn)杯BeanPostProcessors的時候會設(shè)置,如果當(dāng)前Bean實(shí)現(xiàn)了 InstantiationAwareBeanPostProcessor則這個就會是true。
當(dāng)三個條件都存在的時候,就會調(diào)用實(shí)現(xiàn)的 InstantiationAwareBeanPostProcessor接口的 postProcessBeforeInstantiation方法,然后獲取返回的Bean,如果返回的Bean不是null還會調(diào)用實(shí)現(xiàn)的 BeanPostProcessor接口的 postProcessAfterInitialization方法,這里用代碼說明:
3、如果上面3個條件其中一個不滿足就不會調(diào)用實(shí)現(xiàn)的方法。默認(rèn)這里都不會調(diào)用的這些 BeanPostProcessors的實(shí)現(xiàn)方法。然后繼續(xù)執(zhí)行后面的 doCreateBean方法。
2.1 真正的創(chuàng)建Bean,doCreateBean
doCreateBean方法邏輯
這個代碼的實(shí)現(xiàn)還是在 AbstractAutowireCapableBeanFactory方法中。流程是
1、先檢查 instanceWrapper變量是不是null,這里一般是null,除非當(dāng)前正在創(chuàng)建的Bean在 factoryBeanInstanceCache中存在這個是保存還沒創(chuàng)建完成的FactoryBean的集合。
2、調(diào)用createBeanInstance方法實(shí)例化Bean,這個方法在后面會講解
3、如果當(dāng)前 RootBeanDefinition對象還沒有調(diào)用過實(shí)現(xiàn)了的 MergedBeanDefinitionPostProcessor接口的方法,則會進(jìn)行調(diào)用 。
4、 當(dāng)滿足以下三點(diǎn)(1)是單例Bean(2)嘗試解析bean之間的循環(huán)引用(3)bean目前正在創(chuàng)建中則會進(jìn)一步檢查是否實(shí)現(xiàn)了 SmartInstantiationAwareBeanPostProcessor接口如果實(shí)現(xiàn)了則調(diào)用是實(shí)現(xiàn)的 getEarlyBeanReference方法
5、 調(diào)用 populateBean方法進(jìn)行屬性填充,這里后面會講解
6、 調(diào)用 initializeBean方法對Bean進(jìn)行初始化,這里后面會講解
2.1.1 實(shí)例化Bean,createBeanInstance
實(shí)例化Bean
這里的邏輯稍微有一點(diǎn)復(fù)雜,這個流程圖已經(jīng)是簡化過后的了。簡要根據(jù)代碼說明一下流程:
1、先檢查Class是否已經(jīng)關(guān)聯(lián)了,并且對應(yīng)的修飾符是否是public的
2、如果用戶定義了Bean實(shí)例化的函數(shù),則調(diào)用并返回
3、如果當(dāng)前Bean實(shí)現(xiàn)了 FactoryBean接口則調(diào)用對應(yīng)的 FactoryBean接口的 getObject方法
4、根據(jù)getBean時候是否傳入構(gòu)造參數(shù)進(jìn)行處理
4.1 如果沒有傳入構(gòu)造參數(shù),則檢查是否存在已經(jīng)緩存的無參構(gòu)造器,有則使用構(gòu)造器直接創(chuàng)建,沒有就會調(diào)用 instantiateBean方法先獲取實(shí)例化的策略默認(rèn)是 CglibSubclassingInstantiationStrategy,然后實(shí)例化Bean。最后返回
4.2 如果傳入了構(gòu)造參數(shù),則會先檢查是否實(shí)現(xiàn)了 SmartInstantiationAwareBeanPostProcessor接口,如果實(shí)現(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)造器實(shí)例化Bean并返回,如果都不滿足,則會根據(jù)構(gòu)造參數(shù)選擇合適的有參構(gòu)造器然后實(shí)例化Bean并返回
5、如果上面都沒有合適的構(gòu)造器,則直接使用無參構(gòu)造器創(chuàng)建并返回Bean。
2.1.2 填充Bean,populateBean
填充Bean
這里還是根據(jù)代碼來說一下流程
1、檢查當(dāng)前Bean是否實(shí)現(xiàn)了 InstantiationAwareBeanPostProcessor的 postProcessAfterInstantiation方法則調(diào)用,并結(jié)束Bean的填充。2、將按照類型跟按照名稱注入的Bean分開,如果注入的Bean還沒有實(shí)例化的這里會實(shí)例化,然后放到 PropertyValues對象中。3、如果實(shí)現(xiàn)了 InstantiationAwareBeanPostProcessor類的 postProcessProperties則調(diào)用這個方法并獲取返回值,如果返回值是null,則有可能是實(shí)現(xiàn)了過期的 postProcessPropertyValues方法,這里需要進(jìn)一步調(diào)用 postProcessPropertyValues方法4、進(jìn)行參數(shù)填充
2.1.3 初始化Bean,initializeBean
初始化Bean
同時這里根據(jù)代碼跟流程圖來說明
1、如果Bean實(shí)現(xiàn)了 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware則調(diào)用對應(yīng)實(shí)現(xiàn)的方法 。
2、Bean不為null并且bean不是合成的,如果實(shí)現(xiàn)了 BeanPostProcessor的 postProcessBeforeInitialization則會調(diào)用實(shí)現(xiàn)的 postProcessBeforeInitialization方法。在 ApplicationContextAwareProcessor類中實(shí)現(xiàn)了 postProcessBeforeInitialization方法。而這個類會在Spring刷新容器準(zhǔn)備 beanFactory的時候會加進(jìn)去,這里就會被調(diào)用,而調(diào)用里面會檢查Bean是不是 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware的實(shí)現(xiàn)類。這里就會調(diào)用對應(yīng)的實(shí)現(xiàn)方法。代碼如下
1、實(shí)例化Bean然后,檢查是否實(shí)現(xiàn)了 InitializingBean的 afterPropertiesSet方法,如果實(shí)現(xiàn)了就會調(diào)用
2、Bean不為null并且bean不是合成的,如果實(shí)現(xiàn)了 BeanPostProcessor的 postProcessBeforeInitialization則會調(diào)用實(shí)現(xiàn)的 postProcessAfterInitialization方法。
到此創(chuàng)建Bean 的流程就沒了,剩下的就是容器銷毀的時候的了
三、destory方法跟銷毀Bean
Bean在創(chuàng)建完畢之后會檢查用戶是否指定了 destroyMethodName以及是否實(shí)現(xiàn)了 DestructionAwareBeanPostProcessor接口的 requiresDestruction方法,如果指定了會記錄下來保存在 DisposableBeanAdapter對象中并保存在bean的 disposableBeans屬性中。代碼在 AbstractBeanFactory的 registerDisposableBeanIfNecessary中
在銷毀Bean的時候最后都會調(diào)用 AbstractAutowireCapableBeanFactory的 destroyBean方法。
這里是創(chuàng)建一個 DisposableBeanAdapter對象,這個對象實(shí)現(xiàn)了Runnable接口,在實(shí)現(xiàn)的 run方法中會調(diào)用實(shí)現(xiàn)的 DisposableBean接口的 destroy方法。并且在創(chuàng)建 DisposableBeanAdapter對象的時候會根據(jù)傳入的bean是否實(shí)現(xiàn)了 DisposableBean接口來設(shè)置 invokeDisposableBean變量,這個變量表實(shí)有沒有實(shí)現(xiàn) DisposableBean接口
四、總結(jié)
最后來一個大的流程
實(shí)例化前的準(zhǔn)備階段
實(shí)例化前
實(shí)例化后
初始化前
本文名稱:11張流程圖搞定SpringBean生命周期
標(biāo)題網(wǎng)址:http://www.dlmjj.cn/article/cdhjcsc.html


咨詢
建站咨詢
