循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终造成闭环。⽐如A依赖于B,B依赖于C,C⼜依赖于A
java
Spring中循环依赖场景有:spring
其中,构造器的循环依赖问题⽆法解决,只能拋出 BeanCurrentlyInCreationException 异常,在解决属性循环依赖时,spring采⽤的是提早暴露对象的⽅法。缓存
//lagouBen 依赖于 ItBean public class LagouBean { private ItBean itBean; public void setItBean(ItBean itBean) { this.itBean = itBean; } public LagouBean() { System.out.println("LagouBean 构造器"); } }
//ItBean 依赖于 LagouBen public class ItBean { private LagouBean lagouBean; public void setLagouBean(LagouBean lagouBean) { this.lagouBean = lagouBean; } public ItBean() { System.out.println("ItBean...构造器"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="lagouBean" class="com.lagou.edu.LagouBean" > <property name="ItBean" ref="itBean>"></property> </bean> <bean id="itBean" class="com.lagou.edu.ItBean" > <property name="LagouBean" ref="lagouBean>"></property> </bean> </beans>
A依赖于B ,B 依赖于A函数
A在建立过程当中 :this
首先会建立Bean实例(仅仅调用构造方法,可是还没有设置属性,经过反射完成对象的初始化),prototype
而后判断是不是单例,是否有循环依赖。code
把建立好的Bean实例放入三级缓存——singletonFactories
xml
而后将要给A Bean装配属性,发现依赖B
对象
调用deGetBean() 想拿到B,首先从一级缓存(singletonObjects)中拿,而后从二级缓存中(earlySingletonObjects)拿,而后从三级缓存(singletonFactories)拿,都拿不到,那就开始建立B Bean
blog
把建立好的B Bean实例放入三级缓存——singletonFactories,发现依赖于A
调用deGetBean() 想拿到A,首先从一级缓存(singletonObjects)中拿,而后从二级缓存中(earlySingletonObjects)拿,都没拿到。而后从三级缓存中拿,拿到了
拿到A Bean以后如上图,放到二级缓存(earlySingletonObjects)中,而后从三级缓存(singletonFactories)中删除。而后给B bean赋值了。
此时B Bean 就装配好了 放入一级缓存池中。
B 装配好了以后,A 就能顺利的装配了,而后调用addSingleton()
方法,把A 从二级三级缓存中删除,而后放到一级缓存也就是单例池中。
完成
注意:
这个案例中,B不会放到二级缓存,只有在B依赖的一个对象还没有实例化的时候才会把B放到二级缓存。例如:
A依赖B,B依赖A和C,C依赖B。 先建立A,把还没有赋值的A放到三级缓存,而后赋值B,找不到B,而后建立B,而后把还没有赋值的B放到三级缓存,而后在建立B的过程当中从三级缓存找A(同时把A从三级缓存中删除而后加入到二级缓存),而后B还有个属性C,赋值C,从缓存中找不到C,而后建立C,而后把还没有赋值的B放到三级缓存,建立C的过程当中发现C依赖于B,而后能够从三级缓存中找到B,而后把B放到二级缓存,C就装配完毕了,放到一级缓存。同时B也有了A和C,B装配完毕了,放到一级缓存。 A依赖B,B已经OK了,那么A也装配完毕了。
/** Cache of singleton factories: bean name to ObjectFactory. */ //三级缓存 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of early singleton objects: bean name to bean instance. */ //二级缓存 private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); /** Cache of singleton objects: bean name to bean instance. */ //一级缓存 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);