上QQ阅读APP看书,第一时间看更新
2.3.2 循环依赖解决方案
让我们回顾2.1.3节中基于Setter方法注入的循环依赖场景,如代码清单2-21所示。
代码清单2-21 基于Setter方法注入的循环依赖代码
public class ClassA { private ClassB classB; @Autowired public void setClassB(ClassB classB) { this.classB = classB; } } public class ClassB { private ClassA classA; @Autowired public void setClassA(ClassA classA) { this.classA = classA; } }
现在假设我们先初始化ClassA。ClassA首先通过createBeanInstance()方法创建了实例,并且将这个实例提前暴露到第三级缓存singletonFactories中。然后,ClassA尝试通过populateBean()方法注入属性,发现自己依赖ClassB这个属性,就会尝试去获取ClassB的实例。
显然,这时候ClassB还没有被创建,所以要走创建流程。ClassB在初始化第一步的时候发现自己依赖了ClassA,就会尝试从第一级缓存singletonObjects去获取ClassA的实例。因为ClassA这时候还没有被创建完毕,所以它在第一级缓存和第二级缓存中都不存在。当尝试访问第三级缓存时,因为ClassA已经提前暴露了,所以ClassB能够通过singletonFactories拿到ClassA对象并顺利完成所有初始化流程。
ClassB对象创建完成之后会被放到第一级缓存中,这时候ClassA就能从第一级缓存中获取ClassB的实例,进而完成ClassA的所有初始化流程。这样ClassA和ClassB都能够成功完成创建过程,整个流程如图2-3所示。
图2-3 基于Setter方法注入的循环依赖解决流程
讲到这里,相信你也理解了为什么构造器注入无法解决循环依赖问题。这是因为构造器注入过程是发生在Bean初始化的第一个步骤createBeanInstance()中,而这个步骤还没有调用addSingletonFactory()方法完成第三级缓存的构建,自然也就无法从该缓存中获取目标对象。