spring循环依赖是什么?
简单来说就是AB,两个类在相互依赖,那么在spring容器实例化,去创建A,B两个Bean的时候,到底先创建谁呢?先创建ABean,因为ABean中注入了BBean,那么就去先创建BBean,而BBean的创建又需要ABean,这样在创建的时候似乎陷入了一个”死循环“,那么spring是这么解决这个死循环的呢?注意,这里spring 仅仅是解决单例Bean的循环依赖,非单例模式spring是无法处理的。
@Component public class IndexService { @Autowired TestService testService; public IndexService() { // this.name = "xiaoming"; System.out.println("IndexService constructor"); } // private String name ; // // public void getIndex(){ // System.out.println("getIndex"); // } } @Service public class TestService { @Autowired IndexService indexService; public TestService() { System.out.println("TestService constructor"); } }
现在我们一步步debug下
1.1
1.2
1.3
当debug到这里,indexService已经是跑完构造函数的object了。但是它还不是SpringBean,因为它还没有跑完Spring创建Bean的全部流程。图1.1中,红框的部分,在调用indexService构造函数,调用一些内置的BeanPostProcessor 之后,indexServic提前暴露了它的BeanFactory,可以看图1.3的代码,在这里方法中,indexService的factory已经被缓存了起来,这个factory可以理解我们再工厂中生产indexService的”模板“。在调用this.populateBean(beanName, mbd, instanceWrapper)就是我们给indexService填充它内部属性之前,我们先缓存一份它的”生产模板“,这个缓存就是spring 二级缓存,也是解决spring 循环依赖的关键。
2
我们继续debug,在this.populateBean(beanName, mbd, instanceWrapper)方法中,indexService需要填充testService属性,那我们就去单例池里面拿(spring所有创建成功的bean都会放在singletonObjects里面,这个称为单例池,也称为spring一级缓存),调用getSingleton(”testService“),发现没有,因为这个时候我们还没创建testService的Bean,既然我们在indexService中我们要引用了testService,结果没有,那么spring就去创建testService了,重新开始走创建testService的Bean的流程,
看图2.1,又走到了这里,这里同样的方法我们循环了一遍,同样先产生testSeriveBean的object,在填充属性前,在spring二级缓存中存下了testService的”生成模板“即singleFactory。然后填充testService属性的时候,发现我们需要indexService,回看1.1,1.2,1.3三幅debug截图,记住这个时候indexService还不是一个springBean,只是一个object,inddexService的创建流程只跑了一半,indexService是一个earlySingleton。
然后我们继续看,既然testService需要填充indexService,那我们就去拿吧。看图2.2,照样我们也先去调用getSingleton(”indexService“),注意这个时候getSingle("indexService")是有返回的!!可以看下2.3图中的简单逻辑,直接从singletonObejcts中拿indexService肯定没有,因为indexService还只是一个object,而且indexService正在创建中,那么我们就用之前缓存的indexService的singleFatory去创建一个indexService的earlySingleton,而且看2.3图,这里我们得到的indexServic的确是个”早产儿“或者说”半成品“。但是我们可以拿来填充我们的testService了!!!这样我们的testServicBean能顺利被spring生产出来。
这样testServiceBean能先顺利产生,那么我们要创建的indexServiceBean最后也顺利生产出来了。到此,spring借助singletonFactory(Map)二级缓存,解决了单例之前循环依赖的问题。
* 总结图:
黑线部分是spring循环依赖的循环逻辑,红线部分是spring打破这个死循环的大致设计原理。 *
~~~~