spring 三級緩存機制的作用(spring如何解決循環依賴)


spring getBean三級緩存機制的作用
一級緩存:是單例池,所有初始化完成后的單例對象都會存到這里
二級緩存:存放沒有完全被spring初始化完的bean
三級緩存:為了解決循環依賴

場景為:
classA依賴classB,classB也依賴classA
這種情況下,在創建A的時候因為B還沒有被創建,因此無法完成創建,而B又依賴於A,因此B也無法完成創建
這樣就形成了死鎖。spring利用了三級緩存機制解決了這個問題。
spring中,bean的初始化只是其生命周期的一部分(第一步),在bean初始化之后,spring會生成一個ObjectFactory<?>(這是一個函數式接口)存到三級緩存,它的作用是生產一個bean(getObject方法),所有的bean在初始化未完成(對於spring的bean生命周期來說)的時候都會先存一個ObjectFactory<?>到三級緩存。

當A被創建的時候,因為依賴於B這個時候spring會調用getBean("B")(遞歸操作)去獲取B,因為B沒有被加載,所以spring又會去加載B,當B被實例化后設置B的屬性,因為B又是依賴於A的,這個時候spring會先從單例池中取A發現沒有,又從二級緩存取,發現還沒有,最后去三級緩存中取得ObjectFactory(前面說到所有的bean在初始化未完成的時候都會先存入到三級緩存),執行ObjectFactory.getObject()這個方法會調用getEarlyBeanReference方法(函數式接口),這個方法會返回一個bean實例。然后B取得了A完成創建,返回給A,A也得到了B,循環依賴問題被解決。

到這里我有個疑惑,為什么不直接在二級緩存中存bean的實例呢?為什么要使用ObjectFactory函數式接口呢?

查看源碼后發現,getEarlyBeanReference這個方法會判斷傳入的這個類有沒有被AOP增強,如果被AOP增強了,則返回一個被AOP包裝過后的實例(在被AOP增強的時候,返回的是一個代理類(這個時候會重新創建一個實例(createProxy方法)))。


如果直接在二級緩存中存入bean實例(此時沒有被AOP增強),然后去設置了屬性B(B這個時候會去三級緩存中找A(A這個時候沒有被AOP增強)),B屬性設置完成后,A最后會去被AOP增強(這個時候A會重新創建)然后放入到單例池,這個時候B中的A對象就跟單例池里的A對象不是一個對象了。

這個時候又有一個疑問,既然要提前被AOP包裝,為什么不直接把AOP包裝后的類放入到二級緩存呢?而要使用三級緩存呢?
這里應該跟spring的設計思想有關,spring想盡可能的按照常規的bean的生命周期來創建bean,除非要解決循環依賴,不然三級緩存的ObjectFactory永遠都用不到(二級緩存也用不到)。最后在實例被加入到一級緩存的時候,會把二級緩存和三級緩存中的實例移除。


免責聲明!

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



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