Spring中的循環依賴

循環依賴

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

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測試

相關文章
相關標籤/搜索