在使用Spring時,若是主要採用基於構造器
的依賴注入方式,則可能會遇到循環依賴的狀況,簡而言之就是Bean A
的構造器依賴於Bean B
,Bean B
的構造器又依賴於Bean A
。在這種狀況下Spring會在編譯時拋出BeanCurrentlyInCreationException
。java
@Component public 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); } }
@Component public 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
。測試