参考资料:
什么是循环依赖
循环依赖就是循环引用,Bean相互间持有对方,形成闭环。如下图所示,A依赖B,B依赖C,C依赖A
解决循环依赖
spring通过三级缓存的方式来解决循环依赖,要了解这个解决方法,首先需要知道spring bean的生命周期,就是ioc容器创建bean对象实例的过程中所执行的方法。
如上图所示,spring生命周期顺序是先执行构造方法,再设置属性值。
循环依赖的解决思路
先介绍整个解决思路,再来看代码。直接看源码,很容易绕晕。
源码跟踪
先看下两个类之间的依赖关系
<!--循环依赖问题-->
<bean id="lagouBean" class="com.lagou.edu.LagouBean">
<property name="ItBean" ref="itBean"/>
</bean>
<bean id="itBean" class="com.lagou.edu.ItBean">
<property name="LagouBean" ref="lagouBean"/>
</bean>
直接追踪到创建对象实例的方法doCreateBean
接着就是ItBean设置属性,需要找到LaGouBean。
在这里我们已经获取到想要的Bean,就按调用顺序返回,接着执行ItBean剩余的方法,最后把对象实例存储到单例池
执行到这,一级缓存已经有了ItBean的对象实例,LaGouBean只需要从缓存中读取即可。
以上,就是spring处理循环依赖的过程,核心是提前把未完型的对象实例暴露到三级缓存
附上三个缓存的结构
/** Cache of singleton objects: bean name to bean instance. */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /** Cache of early singleton objects: bean name to bean instance. */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); /** Cache of singleton factories: bean name to ObjectFactory. */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);