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注册依赖
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。