spring setter注入为什么可以解决循环依赖 而构造注入不行

spring setter注入为什么可以解决循环依赖 而构造注入不行_第1张图片

上图是单例对象初始化的过程 ,循环依赖发生在 第二步骤


/** Cache of singleton objects: bean name --> bean instance */

private final Map singletonObjects = new ConcurrentHashMap(256);

/** Cache of singleton factories: bean name --> ObjectFactory */

private final Map> singletonFactories = new HashMap>(16);

/** Cache of early singleton objects: bean name --> bean instance */

private final Map earlySingletonObjects = new HashMap(16);


解决方式主要是依赖 spring的三级缓存

singletonObjects ->单例对象的cache 

singletonFactories ->单例对象工厂的cache 

earlySingletonObjects ->提前暴光的单例对象的Cache 

实例分析

A依赖B  B又依赖A

当A创建时 走到下图逻辑 则判断 其BeanDefinition是否为单例 是否允许循环依赖 是否在创建中, 然后满足,调用addSingletonFactory方法


spring setter注入为什么可以解决循环依赖 而构造注入不行_第2张图片

在此方法中,将A放入三级缓存singletonFactories中 然后继续向下走 走到populateBean中 为A设置属性,但是在A的属性中又依赖的B,此时就到三个缓存中分别去找B,但是找不到(因为B此时还未创建),那么接下里就要去创建B

spring setter注入为什么可以解决循环依赖 而构造注入不行_第3张图片

在创建B的过程中,经历与A同样的过程,到设置属性时发现其属性中依赖了A,那么就调用getSingleton去查找A,其过程是先从singletonObjects中获取(找不到 因为此时A还在创建中) 然后再去earlySingletonObjects中找(找不到 因为A还未对外暴露未设置属性的实例) 然后再去singletonFactories中找,因为在创建A时已经把其ObjectFactory放入三级缓存中,所以此时调用其getObject()方法 获取为设置属性的A 并将其放入二级缓存earlySingletonObjects中 将其赋值给B中的A,然后B在执行步骤二和三 完成创建



spring setter注入为什么可以解决循环依赖 而构造注入不行_第4张图片

接着A中的B已经创建完成 此时A接着去执行步骤二,三创建完成

因为A是单例模式,所以此处实例化的A和ObjectFactory.getObject()创建的A指向同一地址,所以此时B中的A也补全完整 从此完成循环依赖

构造注入不能解决循环依赖的原因是:如果A的构造其中依赖了B B的构造器中又依赖了A  在getSingleton中三级缓存需要调用getObject()构造器构造提早暴露但未设置属性的bean,此时就会产生无限递归创建

你可能感兴趣的:(spring setter注入为什么可以解决循环依赖 而构造注入不行)