1. 程式人生 > >Spring中的迴圈依賴

Spring中的迴圈依賴

迴圈依賴

在使用Spring時,如果主要採用基於構造器的依賴注入方式,則可能會遇到迴圈依賴的情況,簡而言之就是Bean A的構造器依賴於Bean B,Bean 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 B,Class B例項化完成後開始設值,而這時Class A已經是例項化完成了的,所以可以成功引用到Class A。