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(); }
运行结果
主要的错误以下:源码分析
Error creating bean with name 'testA': Requested bean is currently in creation: Is there an unresolvable circular reference
下面看看整个流程图:学习
下面看看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(); }
下面看看整个流程图:prototype
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"); }
运行结果:
主要的错误以下:
Error creating bean with name 'testE': Requested bean is currently in creation: Is there an unresolvable circular reference
下面看看整个流程图:
多例的判断,是经过prototypesCurrentlyInCreation来的,建立前设值进去,建立后移除,若是循环依赖,就会出现还没移除又设值的状况,就抛异常了。
建立bean以前,会经过isDependent判断是否循环依赖,没有循环依赖经过registerDependentBean注册依赖