spring循环依赖为什么要使用三级缓存

大家可以看视频:https://www.bilibili.com/video/BV15y4y1z7E4/

回顾下,源码分析:

这里最重要的就在获取三级缓存时候的 getObject().

《spring循环依赖为什么要使用三级缓存》

这里获取的是一个 beanFactory,然后具体的执行是下面的代码:

《spring循环依赖为什么要使用三级缓存》

这块是在首次创建bean实例(还没有属性注入)时候,放入的。

这里就是去获取最终对象,也就是代理后的对象。

我们看下getEarlyBeanReference是个什么东西?他是一个函数式接口

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

继续分析getEarlyBeanReference,也就是singletonFactory.getObject()到底干了什么

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
   Object exposedObject = bean;
  
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
     
for (BeanPostProcessor bp : getBeanPostProcessors()) {
        
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
         }
      }
   }
  
return exposedObject;
}

这里是将我们的后置处理器再次循环,然后找出SmartInstantiationAware后置处理器,后面都是AOP的操作了。

为什么要使用三级缓存:

1.只一级缓存呢? 当然不行,解决不了循环依赖,会形成死循环。

2. 二级缓存呢? 如果二级缓存里面放入bean对象,能解决循环依赖。只是 解决不了AOP场景下的循环依赖。在AOP情形下,注入到其他bean的,不是最终的代理对象,而是原始对象。

3. 二级缓存,如果使用现在的三级缓存结构Map<String, ObjectFactory<?>>.里面放入的是现在函数接口,然后调getObject()获取呢? 这样也不行,那么这就不是一个缓存了,每次都会去取。

4.二级缓存,里面直接放入 代理对象呢? 在实例化bean后,调用addSingletonFactory()时候直接放入代理后的对象,如下代码所示:

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
   Assert.notNull(singletonFactory,
“Singleton factory must not be null”);
  
synchronized (this.singletonObjects) {
     
if (!this.singletonObjects.containsKey(beanName)) {
        
//this.singletonFactories.put(beanName, singletonFactory);
        
this.earlySingletonObjects.put(beanName, singletonFactory.getObject());
        
//this.earlySingletonObjects.remove(beanName);
        
this.registeredSingletons.add(beanName);
      }
   }
}

这样完全可行的。

 

那么为什么spring没这么做呢?Spring 的设计原则是在 Bean 初始化完成之后才延时为其创建代理。

(这个需要回顾AOP原理,创建bean后,在赋值,并且初始化后,会调用后置处理器BeanPostProcessor的postProcessAfterInstantiation()方法.

AbstractAutoProxyCreator实现的postProcessAfterInstantiation()方法.然后创建AOP动态代理)

而三级缓存为了解决循环依赖,不得不提前创建动态代理,而普通的非循环依赖的还是按照bean初始化后创建动态代理,然后放入一级缓存。

 

下面的图是 动态代理 在非循环 和 循环依赖下 创建时机的对比图

《spring循环依赖为什么要使用三级缓存》

 

 

    原文作者:-兰天白云-
    原文地址: https://blog.csdn.net/lan861698789/article/details/109554429
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞