spring学习之源码分析spring如何解决循环依赖

44次阅读

共计 1797 个字符,预计需要花费 5 分钟才能阅读完成。

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();}

运行结果

主要的错误如下:

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

下面看看整个流程图:

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();}

下面看看整个流程图:

多例

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");
}

运行结果:

主要的错误如下:

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

下面看看整个流程图:

多例的判断,是通过 prototypesCurrentlyInCreation 来的,创建前设值进去,创建后移除,如果循环依赖,就会出现还没移除又设值的情况,就抛异常了。

DependsOn

创建 bean 之前,会通过 isDependent 判断是否循环依赖,没有循环依赖通过 registerDependentBean 注册依赖

正文完
 0