为什么Spring要使用三级缓存解决循环依赖?

为什么Spring要使用三级缓存解决循环依赖?

按照理论分析,只需要二级缓存即可以解决循环依赖的问题。
比如存在循环依赖关系:
A->B->A
只使用二级缓存,代码逻辑可能是这样:
为什么Spring要使用三级缓存解决循环依赖?_第1张图片
但是如果引入了AOP,A、B最终拿到的都是代理对象,那么逻辑将会变成这样:
为什么Spring要使用三级缓存解决循环依赖?_第2张图片
而在Spring中,AOP代理对象是计划在Bean完成初始化之后通过BeanPostProcessor处理生成,相关代码如下:
先看一下AbstractAutoProxyCreator这个InitializationAwareBeanPostProcessor的代码:
关键方法:
1、public Object getEarlyBeanReference(Object bean, String beanName)
这个方法是用作三级缓存升级二级缓存的时候调用的,是为了获取二级缓存的时候就把代理对象生成好。

public Object getEarlyBeanReference(Object bean, String beanName) {
     
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        this.earlyProxyReferences.put(cacheKey, bean);
        return this.wrapIfNecessary(bean, beanName, cacheKey);
    }

调用入口AbstractAutowireCapableBeanFactory.getEarlyBeanReference:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
     
......
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
     
            if (this.logger.isTraceEnabled()) {
     
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, () -> {
     
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }
        ......
        }
}

2、public Object postProcessAfterInitialization(@Nullable Object bean, String beanName)
这个方法主要用于没有经过二、三级缓存的实例获取代理对象使用,定义在bean的init方法执行完后才调用,可以看出跟上面的getEarlyBeanReference方法代码差不多。

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
     
        if (bean != null) {
     
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
     
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }

总结

那么回到最初的问题,为什么需要三级缓存?
我个人理解:如果没有三级缓存,AOP场景则为了循环依赖中最终取到的实例是代理对象,则必须在对象实例化的一开始(依赖注入及init方法前)就先生成代理对象,并放到二级缓存中,这样的化就不符合Spring生命周期的设计。按照Spring生命周期的设计原则,AOP生成代理对象的基础是当前对象实例已经初始化完毕(实例+依赖注入+init方法调用+相关BeanPostProcessor调用完毕),因此引入了三级缓存。

你可能感兴趣的:(Spring,spring,java,aop,bean)