簡單理解spring源碼如何加載bean,實例化,初始化和解決循環依賴

在這裏插入圖片描述

在這裏插入圖片描述
spring容器啓動

在這裏插入圖片描述
調用了構造方法的refresh()方法

在這裏插入圖片描述
在倒數第二個方法 裏面做了準備工作和實例化懶加載的單例bean
在這裏插入圖片描述
最後一個方法是實例化懶加載的單例bean

首先,spring加載bean大致分爲4步,getBean,doGetBean,createBean,doCreateBean。
在這裏插入圖片描述
這裏做完判斷以後就會去getBean
在這裏插入圖片描述
進去以後就會看見方法doGetBean

點進去

在這裏插入圖片描述

會在單例池中get這個bean 也就是一級緩存

方法實現:在這裏插入圖片描述
第一次get爲空,並且沒有被暴露
返回null

在這裏插入圖片描述
開始創建bean 調用這個方法 key是beanName value是一個lamda表達式 但並沒有被執行
在這裏插入圖片描述
進來發現是先在一級緩存中get這個bean 如果爲null 下邊掉用了getObject纔是調用了createBean

在這裏插入圖片描述
do開頭的方法是做事情的方法 開始創建bean

在這裏插入圖片描述
這個方法用來實例化bean
在這裏插入圖片描述
進來以後spring會推斷最合適的構造方法 我這個只是測試,調用了最簡單的無慘構造
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
到這裏以後就完成了bean的實例化
然後跳出來

在這裏插入圖片描述
到這裏以後就會把這個bean放入到三級緩存中 這裏傳入的也是個lamda表達式 也是沒有被執行
這個lamda表達式是用來解決aop代理對象的問題,如果使用了代理對象就操作這個方法完成代理,這個我還不太明白
在這裏插入圖片描述
在這裏插入圖片描述
然後開始初始化這個bean 進行依賴注入

在這裏插入圖片描述
發現有一個屬性
然後開始
在這裏插入圖片描述
在這裏插入圖片描述
解析一些必要的屬性值吧應該 我猜的
在這裏插入圖片描述
這是一個還沒準備好的類型
在這裏插入圖片描述
然後getBean 要給A的B屬性裝配
又到doGetBean方法 循環一次

單例池也是獲取不到B 會創建一次B
在實例化B後會給B的A屬性填充 會開始getBean 而A是已經暴露在了三級緩存中,A還是個半成品,但已經可以讓B拿到然後初始化了
在這裏插入圖片描述
這個是getBean的邏輯 首先從一級緩存裏拿,然後是二級三級
拿到這個bean B就完成了屬性的依賴注入 然後開始初始化這個bean
在這裏插入圖片描述
在這裏插入圖片描述
先執行判斷這個bean有沒有實現aware接口 實現了就調用
在這裏插入圖片描述

beanPostProcessors 的postProcessBeforeInitialization方法
在這裏插入圖片描述
執行initmethod方法
在這裏插入圖片描述
beanPostPercessors的postProcessAfterInitialization
然後B就完成了初始化
在這裏插入圖片描述
然後把B放到一級緩存中
然後A也能拿到B的bean

總結一下:spring解決循環依賴主要是將實例化和初始化分開,實例化完成後加入到三級緩存中,使得依賴的bean可以get到他。 bean的加載過程就是首先先在單例池get這個Bean,調用doGetBean方法,如果沒有,會開始創建Bean,doCreateBean,實例化完成後,開始屬性的注入,如果依賴其他bean,流程一樣,最後屬性裝配完成後,開始初始化,調用aware接口,beanPostPorssors的before方法,initMethod,beanPostPorssors的after方法,完成初始化 後續會繼續加油!!!