Spring中的循環依賴

循環依賴

在使用Spring時,如果主要採用基於構造器的依賴注入方式,則可能會遇到循環依賴的情況,簡而言之就是Bean A的構造器依賴於Bean BBean B的構造器又依賴於Bean A。在這種情況下Spring會在編譯時拋出BeanCurrentlyInCreationException

Class A

@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);
    }
}

Class B

@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 BClass B實例化完成後開始設值,而這時Class A已經是實例化完成了的,所以可以成功引用到Class A

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章