Spring循环依赖三级缓存是否可以减少为二级缓存?( 三 )


2、不提前创建好代理对象 , 在出现循环依赖被其他对象注入时 , 才实时生成代理对象 。 这样在没有循环依赖的情况下 , Bean就可以按着Spring设计原则的步骤来创建 。
Sping选择了第二种 , 如果是第一种 , 就会有以下不同的处理逻辑:
1、在提前曝光半成品时 , 直接执行getEarlyBeanReference创建到代理 , 并放入到缓存earlySingletonObjects中 。
2、有了上一步 , 那就不需要通过ObjectFactory来延迟执行getEarlyBeanReference , 也就不需要singletonFactories这一级缓存 。
这种处理方式可行吗?
这里做个试验 , 对AbstractAutowireCapableBeanFactory做个小改造 , 在放入三级缓存之后立刻取出并放入二级缓存 , 这样三级缓存的作用就完全被忽略掉 , 就相当于只有二级缓存 。
Spring循环依赖三级缓存是否可以减少为二级缓存?文章插图
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactoryimplements AutowireCapableBeanFactory {protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {……// 是否提前曝光boolean earlySingletonExposure = (mbd.isSingleton()if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));// 立刻从三级缓存取出放入二级缓存getSingleton(beanName, true);}……}}左右滑动查看完整代码测试结果是可以的 , 并且从源码上分析可以得出两种方式性能是一样的 , 并不会影响到Sping启动速度 。
那为什么Sping不选择二级缓存方式 , 而是要额外加一层缓存?
【Spring循环依赖三级缓存是否可以减少为二级缓存?】如果要使用二级缓存解决循环依赖 , 意味着Bean在构造完后就创建代理对象 , 这样违背了Spring设计原则 。
Spring结合AOP跟Bean的生命周期 , 是在Bean创建完全之后通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来完成的 , 在这个后置处理的postProcessAfterInitialization方法中对初始化后的Bean完成AOP代理 。
如果出现了循环依赖 , 那没有办法 , 只有给Bean先创建代理 , 但是没有出现循环依赖的情况下 , 设计之初就是让Bean在生命周期的最后一步完成代理而不是在实例化后就立马完成代理 。
转自:思否segmentfault