源码阅读:Spring怎么解决循环依赖的
二级缓存解决循环依赖
Spring创建一个对象的流程是 getBean() 实例化 填充属性 初始化
调用栈a中有属性b
getBean("a")
createBeanInstance("a")
polulateBean("a")
//如果a中依赖b
bgetBean("b")
createBeanInstance("b")
polulateBean("b")
initializeBean("b")
initializeBean("a")
如果对象a和b互相依赖则会形成调用栈的死循环。
可以用二级缓存解决:一级缓存是单例池子的缓存 ,二级缓存是半成品对象缓存。
此时调用栈如下
getBean("a") //先从缓存中拿 createBeanInstance("a") //放入二级缓存 polulateBean("a") //如果a中依赖b getBean("b") //先从缓存中拿 createBeanInstance("b") //放入二级缓存 polulateBean("b") initializeBean("b") //放入一级缓存 initializeBean("a") //放入一级缓存
三级缓存解决AOP的循环依赖
上面二级缓存就解决了循环依赖,Spring为什么要用三级缓存呢?
如果对象a和b 是代理对象Proxy$a proxy$b,但此时 二级缓存存放的是a和b对象本身,而不是代理对象
此时就引申出了三级缓存:工厂池缓存
为什么不在二级缓存里面直接放入代理对象
那么为什么spring没这么做呢?Spring 的设计原则是在 Bean 初始化完成之后才延时为其创建代理
而不是先创建代理,在初始化。
参考:https://blog.csdn.net/lan861698789/article/details/109554429
看三级缓存时先回顾AOP原理,创建bean后,在赋值,并且初始化后,会调用后置处理器BeanPostProcessor的postProcessAfterInstantiation()方法.
三级缓存为了解决循环依赖,不得不提前创建动态代理(提前处理),而普通的非循环依赖的还是按照bean初始化后创建动态代理,然后放入一级缓存。
Spring的三级缓存
1,第一级缓存:singletonObjects(单例池缓存)
2,第二级缓存:早期提前暴露的对象缓存earlySingletonObjects(半成品对象缓存)
3,第三级缓存:singletonFactories单例对象工厂缓存(通过提前处理创建代理对象) 三级缓存就干这一件事。
a创建的过程中有人要用到a才会用到这个提前引用
如代码
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 != NULL_OBJECT ? singletonObject : null); }