spring學習之源碼分析--spring如何解決循環依賴

spring學習之源碼分析--bean的建立以及以前的文章,都提到了循環依賴,那此次我們來看看spring是如何解決循環依賴的。
spring學習之注入中,咱們看到了兩種的注入方式,一個是構造函數注入,一個是setter注入。咱們分別看看這兩種方式,各是什麼樣的狀況。spring

構造

TestA的構造函數注入了TestB,TestB的構造函數注入了TestA。segmentfault

public class TestA {
    private TestB testB;

    public TestA(@Autowired TestB testB) {
        this.testB = testB;
    }
}

public class TestB {
    private TestA testA;

    public TestB(@Autowired TestA testA) {
        this.testA = testA;
    }
}

測試代碼函數

@Test
public void testCircleByConstructor() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(TestA.class, TestB.class);
    context.refresh();
}

運行結果
image.png
主要的錯誤以下:源碼分析

Error creating bean with name 'testA': Requested bean is currently in creation: Is there an unresolvable circular reference

下面看看整個流程圖:
image.png學習

setter注入

下面看看setter注入的時候,是怎麼處理的測試

單例

TestC的setter注入了TestD,TestD的setter注入了TestC。跟上面構造函數不一樣的是,這邊是無參構造,因此能夠先實例化,再進行屬性設置。this

public class TestC {
    @Autowired
    private TestD testD;
}
public class TestD {
    @Autowired
    private TestC testC;
}

測試代碼spa

@Test
public void testCircleBySet() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(TestC.class, TestD.class);
    context.refresh();
}

下面看看整個流程圖:
image.pngprototype

多例

TestE的setter注入了TestF,TestF的setter注入了TestE。跟上面不一樣的是,這邊是Scope是prototype。
由於是多例的,因此容器初始化的時候,並不會實例化,只能咱們本身調用的時候實例化。code

@Scope("prototype")
public class TestE {
    @Autowired
    private TestF testF;
}
@Scope("prototype")
public class TestF {
    @Autowired
    private TestE testE;
}

測試代碼

@Test
public void testCircleByPrototype() {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(TestE.class, TestF.class);
    context.refresh();
    context.getBean("testE");
}

運行結果:
image.png
主要的錯誤以下:

Error creating bean with name 'testE': Requested bean is currently in creation: Is there an unresolvable circular reference

下面看看整個流程圖:
image.png
多例的判斷,是經過prototypesCurrentlyInCreation來的,建立前設值進去,建立後移除,若是循環依賴,就會出現還沒移除又設值的狀況,就拋異常了。

DependsOn

建立bean以前,會經過isDependent判斷是否循環依賴,沒有循環依賴經過registerDependentBean註冊依賴
image.png

相關文章
相關標籤/搜索