源码阅读: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);
    }

 

posted @ 2020-07-26 02:02  palapala  阅读(187)  评论(0编辑  收藏  举报