關于循環依賴有的同學寫的很好,貼出來:
https://www.cnblogs.com/tiger-fu/p/8961361.html
https://juejin.cn/post/6844903715602694152#heading-7
https://blog.csdn.net/LeoHan163/article/details/106343857
https://www.cnblogs.com/leeego-123/p/12165278.html
Spring中的循環依賴:
- 構造器循環依賴
是否解決:通過構造器注入構成的循環依賴,此依賴是無法解決的,只能拋出BeanCurrentlyInCreationException異常表示循環依賴。
原因:創建A類時,構造器需要B類,那將去創建B,在創建B類時又發現需要C類,則又去創建C,最終在創建C時發現又需要A,從而形成一個環,沒辦法創建。
實現有循環依賴時拋出異常:
Spring容器會將每一個正在創建的Bean 標識符放在一個“當前創建Bean池(singletonsCurrentlyInCreation)”中,Bean標識符在創建過程中將一直保持在這個池中。
因此如果在創建Bean過程中發現自己已經在“當前創建Bean池”里時將拋出BeanCurrentlyInCreationException異常表示循環依賴。
而對于創建完畢的Bean將從“當前創建Bean池”中清除掉。
- 屬性注入循環依賴
prototype模式:有狀態的bean都使用prototype作用域,無狀態的一般都使用singleton單例作用域。
是否解決:"prototype"作用域bean,Spring容器無法完成依賴注入。
原因:“prototype”作用域的Bean,Spring容器不進行緩存,因此無法提前暴露一個創建中的Bean。
singleton模式
是否解決:是的
單例屬性注入如何解決循環依賴
本質上,是通過將半成品實體(實例化,但還未進行屬性注入的實體)存放到map中實現的。
用到的map
1.singletonObjects 單例對象列表, beanName -> bean實例。
2.singletonFactories 單例工廠列表 beanName -> beanFactory。
3.earlySingletonObjects 循環對象依賴列表,對象在創建之后,進行注入過程中,發現產生了循環依賴,那么會將對象放入到這個隊列,并且從singletonFactories中移除掉。
4.singletonsCurrentlyInCreation 正在創建的單例名稱隊列。
5.registeredSingletons 已經創建成功的單例名稱列表。
假設A與B相互依賴
實例化A之后,此時:
singletonFactories 包含 A
registeredSingletons 包含A
singletonsCurrentlyInCreation 包含A
singletonObjects 不包含A
earlySingletonObjects 不包含A
發現A需要注入B,于是實例化B,之后發現B需要A,于是map中拿到A,此時:
singletonFactories 不包含 A
registeredSingletons 包含A
singletonsCurrentlyInCreation 包含A
singletonObjects 不包含A
earlySingletonObjects 包含A
B獲取了A,實例化、初始化完成,此時:
singletonFactories 不包含B
registeredSingletons 包含B
singletonsCurrentlyInCreation 不包含B
singletonObjects 包含B
earlySingletonObjects 不包含B
A繼續初始化,由于上面B初始化完成,所以可以獲得B,此時:
singletonFactories 不包含A
registeredSingletons 包含A
singletonsCurrentlyInCreation 不包含A
singletonObjects 包含A
earlySingletonObjects 包含A
主要使用了singletonFactories、earlySingletonObjects來解決循環依賴的問題。如果不是使用aop的情況下,使用一個map也可以解決循環依賴的問題。但是如果使用了aop,singletonFactories返回的代理對象每次都是不一樣的,所需需要引入earlySingletonObjects。