Spring 解决循环依赖
Posted lisin-lee-cooper
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 解决循环依赖相关的知识,希望对你有一定的参考价值。
一. Bean的生命周期
二. 什么是什么是三级缓存
/** 1级缓存 Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 2级缓存 Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** 3级缓存 Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
获取单例bean时
protected Object getSingleton(String beanName, boolean allowEarlyReference)
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName))
synchronized (this.singletonObjects)
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null)
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
return singletonObject;
第一步:第一层缓存singletonObjects 中,获取单例bean,拿到了直接使用,没有拿到则拿二级缓存;
第二步:在二级缓存earlySingletonObjects中,提前暴露的Bean;
第三步:在三级缓存中查找对应的工厂对象,利用拿到的工厂对象去获取包装后的bean。
如果不使用三级缓存singletonFactories,无法解决AOP后置增强问题,
多一级缓存意义就是在bean循环引用过程中,发生了AOP增强时,避免返回真实对象而非代理对象Proxy。
三. 为什么用三级缓存不用两级缓存
初始spring是没有解决循环引用问题的,设计原则是 bean 实例化、属性设置、初始化之后 再 生成aop对象,但是为了解决循环依赖但又尽量不打破这个设计原则的情况下,使用了存储了函数式接口的第三级缓存;
如果使用二级缓存的话,可以将aop的代理工作提前到 提前暴露实例的阶段执行; 也就是说所有的bean在创建过程中就先生成代理对象再初始化和其他工作; 但是这样的话,就和spring的aop的设计原则相驳,aop的实现需要与bean的正常生命周期的创建分离; 这样只有使用第三级缓存封装一个函数式接口对象到缓存中, 发生循环依赖时,触发代理类的生成。
以上是关于Spring 解决循环依赖的主要内容,如果未能解决你的问题,请参考以下文章
spring的循环依赖是什么,设计的时候怎么避免,而spring又是怎么解决的?