Spring ioc(4)---如何解決循環依賴


前面說到對象的創建,那么在創建的過程中Spring是怎么又是如何解決循環依賴的呢。前面提到有個三級緩存。就是利用這個來解決循環依賴。打個比方說實例化A的時候,先將A創建(早期對象)放入一個池子中。這個時候雖然屬性沒有賦值,但是容器已經能認識這個是A對象,只是屬性全是null而已。在populateBean方法中對屬性賦值的時候,發現A依賴了B,那么就先去創建B了,又走一遍bean的創建過程(創建B)。同樣也會把B的早期對象放入緩存中。當B又走到populateBean方法的時候,發現依賴了A,好吧,我們又去創建A唄,但是這個時候去創建A,發現我們在緩存能找到A(早期對象)了。就可以把B的A屬性賦值了,這個時候B就初始化完成了。現在回到A調用的populateBean方法中。返回的就是B對象了,對A的B屬性進行賦值就可以了。流程如下:

 

這就是Spring IOC如何解決循環依賴的原理,但是IOC無法解決兩種循環依賴,一種是非單例對象的,因為非單例對象不會放入緩存的。每次都是需要創建。二是通過構造器注入,也無法解決。從上面的流程可以看出,調用構造器創建實例是在createBeanInstance方法,而解決循環依賴是在populateBean這個方法中,執行順序也決定了無法解決該種循環依賴。對於這種,如果喜歡使用lombok的@RequiredArgsConstructor注解的小伙伴就需要注意了,這個注解會生成一個帶所有屬性的構造方法。通過idea直接點開對應的class文件就可以看不看這個構造方法了。

 

問題:解決循環依賴一定要三級緩存嘛?

 

關鍵代碼位置:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory

首先我們的一級緩存是單例緩存池singletonObjects),二級緩存是早期對象(earlySingletonObjects),三級緩存是一個包裹對象ObjectFactory(registeredSingletons),通過getObject獲取到早期對象。

從上面的流程來看,實際上二級緩存已經可以解決循環依賴了,那么為什么Spring還要包裹出來一個三級緩存呢?

Spring Ioc(3)---bean的實例化中的源碼分析我們可以看到調用三級緩存中的getObject方法實際上是調用的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference這個方法。

 

 

那么我就看看這個方法里面干了些什么事情:

執行SmartInstantiationAwareBeanPostProcessor這個類型處理器的getEarlyBeanReference方法。

 

斷點調試,發現Spring原生中實現了這個接口的類org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter,實際上什么事情都沒有干,直接返回了,

 

但是如果是AOP要切的對象,會在這里生成代理對象返回,AOP流程:Spring aop(1)--- 尋找切面和代理對象執行流程源碼分析

 

 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference。

所以說第三級緩存其實是為了解決代理對象之間的循環依賴。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM