Water2Wine

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1. 循环依赖的原因

beanA依赖beanB,beanB依赖beanA,导致两者都不能被创建,发生在填充属性的环节

2. 循环依赖的解决方案

提前曝光机制+三级缓存

提前曝光:
正常来说bean的创建过程有三步:实例化->填充属性->初始化,提前曝光就是实例化后填充属性前将bean放入缓存

三级缓存:
singletonObjects:一级缓存,用于存放完全初始化好的bean,从改缓存中取出的bean可以直接使用
earlySingletonObjects:二级缓存,用于存放提前曝光的单例对象的cache,存放原始的bean对象(尚未填充属性)
singletoneFactories:三级缓存,存放提前曝光的bean的工厂,用于生产二级缓存提前曝光的实例

currentlyInCreation:正在创建的bean集合,在bean开始创建时放值,创建完成时移出

alreadyCreated:bean被创建完成后,会放进这个set集合

先从一级缓存获取bean->从二级缓存获取->如果工厂可以创建bean,就从三级缓存获取,并且将三级缓存中的bean移到二级缓存

public interface ObjectFactory<T> {
	T getObject() throws BeansException;
}

加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决

3. 整个从创建bean到解决循环依赖的过程

context.getBean(A.class)->实例化->放入缓存->依赖注入B->getBean(B)->实例化B并放入缓存->B依赖注入A->getBean(A)获取到了缓存中的值并正常返回->B初始化成功->A初始化成功

4. 循环依赖建议

业务代码中尽量不要使用构造器注入,三级缓存解决不了构造器循环依赖的问题

业务代码中为了简介,尽量使用field注入而不是setter方法注入

posted on 2020-08-18 18:12  Water2Wine  阅读(181)  评论(0编辑  收藏  举报