拉勾Java高薪訓練營之Spring:Bean的加載以及循環(huán)依賴處理

一.三級緩存的作用

? ? 在了解Bean的初始化之前,要先了解Bean的三級緩存?以及各自的作用

一級緩存(singletonObjects):單例池?

二級緩存(earlySingletonObjects):早期單例對象? (反射生成的對象?可能屬性還沒有填充完畢,執(zhí)行過了Bean的后置處理器?以及aop生成的? ?二級緩存是為了對象復用)

三級緩存(singletonFactories):單例工廠對象?用于反射生成對象

三級緩存是為了解決循環(huán)依賴而產(chǎn)生的(使用三級緩存而不是用二級緩存是因為?一級緩存中單例池為了保證對象的單一性? 即是?只存完整的對象?而不是既有完整對象?又有不完整對象):

使用場景:ABean?依賴屬性BBean?同樣bBean也依賴ABean如下:

解決過程如下:

1,lagouBean實例化?實例化過程中檢測有沒有依賴ItBean或其他Bean?沒有則直接完成所有屬性注入放在?單例池中?如果有依賴其他Bean?則放入單例工廠池等待其他依賴Bean注入

2.依賴屬性ItBean?實例化,發(fā)現(xiàn)itBean含有依賴屬性含有依賴屬性lagoubean?將itbean放入單例工廠池,?同時從單例工廠池中取出lagoubean完成itBean注入,

3.在上述過程中?獲取lagouBean?時候?將反射生成對象放入二級緩存,以備復用?在itBean完成屬性注入后?刪除單例工廠池中的工廠對象

4.lagouBean完成itBean屬性注入?將對象放入單例池?同時刪除二級緩存的對象

二.?bean的實例化過程

Bean創(chuàng)建?流程??在AbstractApplicationContext#refresh()?法的finishBeanFactoryInitialization(beanFactory) 處

進?finishBeanFactoryInitialization

繼續(xù)進?DefaultListableBeanFactory類的preInstantiateSingletons?法,我們找到下?部分的代碼,看到??Bean或者普通Bean,最終都是通過getBean的?法獲取實例

繼續(xù)跟蹤下去,我們進?到了AbstractBeanFactory類的doGetBean?法,

該方法?嘗試從緩存中獲取對象?在循環(huán)依賴中要用到

如果是第一次創(chuàng)建,則進入createBean方法

接著進?到AbstractAutowireCapableBeanFactory類的?法,找到以下代碼部分



所以這就是構造器注入不能解決循環(huán)依賴的原因?

下面是bean的屬性填充?以及后置處理器

三? 循環(huán)依賴源碼解析

實例化danlibean過程中會存在循環(huán)依賴

進入createBean方法后?可以看到將實力好的對象放入了三級緩存? 此時是沒有進行屬性注入的

然后進入


進入方法最下面的applyPropertyValues方法


可以看到他依賴了ItBean? 進入valueResolver.resolveValueIfNecessary方法

進入resolveReference?方法

從工廠中取ItBean

進入后?其實還是doCreateBean方法?在這里初始化bean并放入單例池?供lagouBean后續(xù)使用

同樣進入getSingleton?方法?過程中執(zhí)行doCreateBean?在該方法中完成依賴注入? 同樣執(zhí)行


然后進行屬性的注入獲取lagouBean

進入方法后

此時三級緩存中是有值得

也可以看出三級緩存機構

獲取到Ilagoubean?并移除三級緩存中數(shù)據(jù)

二級緩存的數(shù)據(jù)類型是

實例化完成后進入getSingleton?將itbean放入一級緩存


一級緩存結構

此時完成itbean注冊

此時回到lagoubean注冊流程

后續(xù)操作完成放置到一級緩存中

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容