spring循环依赖

230 阅读1分钟

参考资料:

1.spring如何解决循环依赖问题

2.图解spring循环依赖

什么是循环依赖

循环依赖就是循环引用,Bean相互间持有对方,形成闭环。如下图所示,A依赖B,B依赖C,C依赖A

image-20201102211204271

解决循环依赖

spring通过三级缓存的方式来解决循环依赖,要了解这个解决方法,首先需要知道spring bean生命周期,就是ioc容器创建bean对象实例的过程中所执行的方法。

image-20201102212418063

如上图所示,spring生命周期顺序是先执行构造方法,再设置属性值

循环依赖的解决思路

先介绍整个解决思路,再来看代码。直接看源码,很容易绕晕。

image-20201102214433662

源码跟踪

先看下两个类之间的依赖关系

	<!--循环依赖问题-->
	<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

image-20201102220941583


image-20201102221111261


image-20201102221222420


image-20201102221413396


image-20201102221537046


image-20201102221838341


image-20201102222004688


接着就是ItBean设置属性,需要找到LaGouBean

image-20201102222219996

image-20201102222452309


在这里我们已经获取到想要的Bean,就按调用顺序返回,接着执行ItBean剩余的方法,最后把对象实例存储到单例池

image-20201102223443334


执行到这,一级缓存已经有了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);