循環依賴
定義: 循環依賴就是循環引用,就是兩個或多個Bean相互之間的持有對方,比方CircularityA引用CircularityB,CircularityB引用CircularityC,CircularityC引用CircularityA。形成一個環狀引用關係。
在使用Spring時,如果主要採用基於構造器的依賴注入方式,則可能會遇到循環依賴的情況,簡而言之就是Bean A的構造器依賴於Bean B,Bean B的構造器又依賴於Bean A。在這種情況下Spring會在編譯時拋出BeanCurrentlyInCreationException。
Class A
@Componentpublic class ClassA { private ClassB classB; @Autowired public ClassA(ClassB classB) { this.classB = classB; } public void printClass() { System.out.println("Class A = " + this); System.out.println("Class B = " + classB); }}Class B
@Componentpublic class ClassB { private ClassA classA; @Autowired public ClassB(ClassA classA) { this.classA = classA; } public void printClass() { System.out.println("Class A = " + classA); System.out.println("Class B = " + this); }}測試
@ContextConfiguration(classes = {ClassA.class, ClassB.class})@RunWith(SpringRunner.class)public class MyTest { @Autowired private ClassA classA; @Autowired private ClassB classB; @Test public void name() { classA.printClass(); classB.printClass(); }}原因
這時候運行測試就會發現拋出了BeanCurrentlyInCreationException異常。產生這種情況的原因是,Spring在創建Bean時,會首先實例化對象,然後再注入依賴。假設Spring首先創建Class A,那麼就會發現在構造器裡有Class B的依賴,所以就會轉去創建Class B,又在Class B的構造器裡發現了對Class A的依賴,而此時Class A是還未初始化完的,因此又會轉去創建Class A,這樣就陷入了死循環。
解決方法
換成基於setter的依賴注入即可解決這個問題。因為基於setter的依賴注入會首先調用默認構造函數來實例化對象,然後再調用setter實現依賴注入。這樣在對象實例化的階段就沒有了任何依賴,因此Class A實例化完成後再調用Class B,Class B實例化完成後開始設值,而這時Class A已經是實例化完成了的,所以可以成功引用到Class A。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。