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

相关文章
相关标签/搜索