什么是循环依赖
它发生在一个Bean A依赖于另一个Bean b,而b反过来也依赖于a的情况。
比如下列情况:
当然可能不止这样,可能是A->B->C->D->E->A这样的循环依赖甚至更多
为了解决循环依赖,我们引入了二层缓冲和三层缓冲。
我们看下面的代码
@Service
public class TestService1 {
@Autowired
private TestService2 testService2;
public void test1() {
}
}
@Service
public class TestService2 {
@Autowired
private TestService1 testService1;
public void test2() {
}
}
他也是个循环依赖, 但在spring里没有问题,因为spring自己帮我们解决了这个问题。
Spring里的循环依赖
循环依赖出现于一下场景:
spring内部有三级缓存:
- singletonObjects 一级缓存,用于保存实例化、注入、初始化完成的bean实例
- earlySingletonObjects 二级缓存,用于保存实例化完成的bean实例
- singletonFactories 三级缓存,用于保存bean创建工厂,以便于后面扩展有机会创建代理对象。
对于上面的代码(单例的setter注入),spring内部是这么实现的
而从图中看好像只需要一层三级缓存即可,那二层缓存为什么还需要存在呢?
这是因为,第三级缓存里保存的并非真正的实例对象,而是ObjectFactory
对象。通过它创建的实例对象每次可能都不一样。如果没有二层缓存,那发生多次依赖调用,如1调用23,2调用1,3调用1,2已经访问过一次三级缓存了,等到3时,在访问一次ObjectFactory
对象,那二者创建的可能不是同一个对象,就会出错。
针对这种场景spring是怎么做的呢?
我们查看源码,发现在AbstractAutowireCapableBeanFactory
类doCreateBean
方法的这段代码中有这一行代码:
它定义了一个匿名内部类,通过getEarlyBeanReference
方法获取代理对象,其实底层是通过AbstractAutoProxyCreator
类的getEarlyBeanReference
生成代理对象。