回答:循環依賴就是循環引用,就是兩個或多個Bean相互之間的持有對方,比如CircleA引用CircleB,CircleB引用CircleA,則它們最終反映為一個環。
Spring如何解決循環依賴?
假設場景如下,A->B->A
1、實例化A,並將未注入屬性的A暴露出去,即提前曝光給容器Wrap
2、開始為A注入屬性,發現需要B,調用getBean(B)
3、實例化B,並注入屬性,發現需要A的時候,從單例緩存中查找,沒找到時繼而從Wrap中查找,從而完成屬性的注入
4、遞歸完畢之后回到A的實例化過程,A將B注入成功,並注入A的其他屬性值,自此即完成了循環依賴的注入
spring中的循環依賴會有3種情況:
1.構造器循環依賴
構造器的循環依賴是不可以解決的,spring容器將每一個正在創建的bean標識符放在一個當前創建bean池中,在創建的過程一直在里面,如果在創建的過程中發現已經存在這個池里面了,這時就會拋出異常表示循環依賴了。
2.setter循環依賴
對於setter的循環依賴是通過spring容器提前暴露剛完成構造器注入,但並未完成其他步驟(如setter注入)的bean來完成的,而且只能決定單例作用域的bean循環依賴,通過提前暴露一個單例工廠方法,從而使其他的bean能引用到該bean.當你依賴到了該Bean而單例緩存里面有沒有該Bean的時候就會調用該工廠方法生產Bean,
Spring是先將Bean對象實例化之后再設置對象屬性的
Spring先是用構造實例化Bean對象,此時Spring會將這個實例化結束的對象放到一個Map中,並且Spring提供了獲取這個未設置屬性的實例化對象引用的方法。
為什么不把Bean暴露出去,而是暴露個Factory呢?因為有些Bean是需要被代理的
3.prototype范圍的依賴
對於“prototype”作用域bean,Spring容器無法完成依賴注入,因為“prototype”作用域的bean,Spring容器不進行緩存,因此無法提前暴露一個創建中的Bean。
文章出處:https://blog.csdn.net/hezuo1181/article/details/82831080
