spring学习之源码分析--bean的创建以及之前的文章,都提到了循环依赖,那这次咱们来看看spring是如何解决循环依赖的。
spring学习之注入中,我们看到了两种的注入方式,一个是构造函数注入,一个是setter注入。我们分别看看这两种方式,各是什么样的情况。

构造

TestA的构造函数注入了TestB,TestB的构造函数注入了TestA。

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。跟上面构造函数不同的是,这边是无参构造,所以可以先实例化,再进行属性设置。

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

测试代码

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

下面看看整个流程图:
image.png

多例

TestE的setter注入了TestF,TestF的setter注入了TestE。跟上面不同的是,这边是Scope是prototype。
因为是多例的,所以容器初始化的时候,并不会实例化,只能我们自己调用的时候实例化。

@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


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆