Spring的三级缓存浅析

本文详细介绍了Spring的三级缓存工作原理,包括一级、二级和三级缓存的作用,以及在循环依赖和AOP场景下的应用。通过关键类如AbstractBeanFactory、AbstractAutowireCapableBeanFactory等的分析,揭示了三级缓存在处理循环依赖和确保正确创建代理对象中的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考资料:
spring为什么使用三级缓存而不是两级? - 知乎 (zhihu.com)

【超级干货】为什么spring一定要弄个三级缓存? - 知乎 (zhihu.com)

关键类:

  1. AbstractBeanFactory:getBean、doGetBean
  2. AbstractAutowireCapableBeanFactory:createBean、doCreateBean、getEarlyBeanReference
  3. DefaultSingletonBeanRegistry:getSingleton
  4. AbstractAutoProxyCreator:getEarlyBeanReference、postProcessAfterInitialization
//AbstractBeanFactory
//两个不同的getSingleton就是三级缓存的关键之处
protected <T> T doGetBean(
    final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    throws BeansException {

    final String beanName = transformedBeanName(name);
    Object bean;
	//尝试从缓存里拿这个bean,这里的getSingleton和下面的不同
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    //缓存里拿不到,创建一个bean
    else {
        //这个getSingleton和上面的不同,它不是从缓存里拿,它要创建一个bean
        //最终调用工厂的getObject,而getObject实质上就是createBean
        if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return createBean(beanName, mbd, args);
                }
            });
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
    }

	//……
    return (T) bean;
}
//DefaultSingletonBeanRegistry
//用工厂创建bean的getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 将当前的bean标记为正在创建中
            beforeSingletonCreation(beanName);
            //调用上面传过来的工厂的getObject方法创建对象
            //联系上文,实际上调用了createBean->doCreateBean
            singletonObject = singletonFactory.getObject();
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = null;
            }
            // 取消当前bean的创建中标记
            afterSingletonCreation(beanName);
            //将创建出来的bean注入一级缓存,并去除二级三级缓存的相关信息
            addSingleton(beanName, singletonObject);
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

//从缓存里拿bean的getSingleton,处理AOP
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) {
                    //从三级缓存里拿出工厂,然后调用它的getObject
                    //联系下文,这里其实调用了getEarlyBeanReference
                    singletonObject = singletonFactory.getObject();
                    //将工厂从三级缓存里去除,将工厂生产出来的bean注入到二级缓存里
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
//AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
    throws BeanCreationException {
	//构造一个原生的bean
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    mbd.resolvedTargetType = beanType;

    //判定当前的bean是否正在创建中
    boolean earlySingletonExposure =; //……&&isSingletonCurrentlyInCreation(beanName)
	
    //将一个匿名的工厂放进三级缓存,这个工厂调用了getEarlyBeanReference
    //这里是三级缓存的关键,检查getEarlyBeanReference
    if (earlySingletonExposure) {
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    //初始化这个bean,注入对象字段的值,这里产生循环依赖
    //如果没有循环依赖且有代理,这里返回代理,否则返回原对象
    //initializeBean方法会调用bean所有的后置处理器,而AOP的代理就是在后置处理器中完成的
    Object exposedObject = bean;
    populateBean(beanName, mbd, instanceWrapper);
    exposedObject = initializeBean(beanName, exposedObject, mbd);

    //从一级和二级缓存中获取该bean,如果有就替换掉原来的bean
    //这是为了解决循环依赖时,AOP后置处理器提前执行导致initialize返回原bean的问题
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            //……
        }
    }
    
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
    return exposedObject;
}
//AbstractAutowireCapableBeanFactory
//遍历所有的后置处理器,挑出AOP的后置处理器提前执行
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    Object exposedObject = bean;
    if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            //如果对象被AOP代理了,他就会进入这个分支,返回代理对象(前提是这是第一次进行代理)
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                if (exposedObject == null) {
                    return null;
                }
            }
        }
    }
    return exposedObject;
}
//AOP的后置处理器:AbstractAutoProxyCreator
//后置代理
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        //从这里就可以看出如果提前执行了,后置处理器不会再执行
        //只有第一个bean会返回代理bean,其他的都返回自身
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
//提前代理,发现它是可以对同一个对象执行多次的,所以单例生产完代理一定要清除三级缓存
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    if (!this.earlyProxyReferences.contains(cacheKey)) {
        //在这里加上了,后置处理就不会执行了
        this.earlyProxyReferences.add(cacheKey);
    }
    return wrapIfNecessary(bean, beanName, cacheKey);
}

总结:

  1. 三个缓存

    1. 一级缓存:保存已经完全可用的bean
    2. 二级缓存:保存未初始化的原bean或者代理bean(AOP)
    3. 三级缓存:保存FactoryBean,这个工厂并没有生产原bean的能力,调用它就是找到AOP后置处理器,然后根据原bean生成一个代理
  2. 无循环依赖的流程,从doGetBean开始

    1. 通过getSingleton从缓存1~3中拿bean,因为没有循环依赖,所以肯定为空
    2. 通过重载过的getSingleton创建一个原bean,实质上调用doCreateBean
    3. doCreateBean通过反射创建一个原bean,将原bean封装在一个FactoryBean中,注入三级缓存
    4. 注入属性、初始化,最后执行后置处理器,通过initializeBean调用applyBeanPostProcessorsBeforeInitialization执行后置处理器
    5. AOP的后置处理器执行,调用AbstractAutoProxyCreator 生成代理对象,由于是第一次调用AbstractAutoProxyCreator#getEarlyBeanReference ,所以会生成代理,而非直接返回原对象
    6. 检测一级和二级缓存,准备替换最终对象,发现是空的,所以不替换
    7. 清空二级和三级缓存
    8. 返回代理bean
  3. 循环依赖的流程,从doGetBean开始

    1. 通过getSingleton从缓存1~3中拿bean,因为刚开始,所以肯定为空
    2. 通过重载过的getSingleton创建一个原bean,实质上调用doCreateBean
    3. doCreateBean通过反射创建一个原bean,将原bean封装在一个FactoryBean中,注入三级缓存
    4. 注入属性,由于循环依赖,所以创建bean2的时候又会获取bean,进入doGetBean
    5. 通过getSingleton从缓存1~3中拿bean,由于缓存3有一个FactoryBean,所以通过FactoryBean获取bean,FactoryBean调用getObject,getObject调用getEarlyBeanReference
    6. getEarlyBeanReference 找到AOP的后置处理器提前执行,生成代理,其原理和initialize完成AOP一样。然后注入二级缓存,删除三级缓存。
    7. 回到bean的初始化过程,现在属性注入完成,要执行后置处理器了。
    8. AOP的后置处理器执行,调用AbstractAutoProxyCreator 生成代理对象,由于是第二次调用AbstractAutoProxyCreator#getEarlyBeanReference ,所以不会生成代理,返回原对象
    9. 检测一级和二级缓存,准备替换最终对象,发现二级缓存有东西,替换掉后置处理器返回的原bean
    10. 清空二级和三级缓存
    11. 返回代理bean
  4. 可以看到关键点就是两个getSingleton,两个FactoryBean以及后置处理器

    1. 两个getSingleton:

      1. 第一个getSingleton尝试从1~3级缓存中获取bean,第三级缓存获取到factorybean时会调用它的getObject方法来得到bean
      2. 第二个getSingleton单纯就是通过传入的factoryBean来获取bean
    2. 两个FactoryBean:

      1. 第一种FactoryBean是在反射创建完一个空对象后注入到三级缓存中的。它的getObject调用了getEarlyBeanReference,本质上就是让后置处理器立刻执行,所以此时如果有AOP,代理对象就会在此处生成(前提是调用了这个FactoryBean,也就是有循环依赖)
      2. 第二种FactoryBean是在第二次调用getSingleton时注入到该方法中的,它调用了createBean,本质上就是反射创建空对象
    3. 后置处理器:在一般的流程中,对象初始化完后就会执行所有后置处理器,而AOP也通过后置处理器完成。但是如果有循环依赖,就会在第二次getBean的时候提前执行一次AOP的后置处理器

      普通情况:
      getBean1->doCreate->populate->initialize->执行所有后置处理器
      
      循环依赖:
      getBean1->doCreate->populate->某个bean又依赖了bean1->getBean1
      ->从三级缓存里获取factorybean->factorybean启动了bean1的AOP后置处理器
      ->populate结束,返回bean1的流程->initialize bean1->执行bean1的所有后置处理器
      
    4. 所以三级缓存本质上就是为了优雅地提前AOP的后置处理器执行设计的。

      1. 如果没有AOP,两层缓存足矣,生产一个空bean就注入二级缓存,循环依赖就从二级缓存里拿。
      2. 但如果有AOP,这样就会导致另外的bean拿到的不是代理对象,所以生产bean时就要直接生成一个代理对象,但是AOP原来就是设计在后置处理器里完成的,这样就破坏了原先的设计,而且我们还要分清楚代理对象和原对象,因为属性是要注入到原对象里面的。
      3. 所以需要设计一种结构
        1. 第一次获取时得到原对象,让属性注入给原对象
        2. 而第二次获取时得到代理对象,让依赖该对象的得到代理对象
        3. 同时AOP要在后置处理器里完成
        4. 而且最后要返回代理对象,且这个代理对象是其他循环依赖对象中的那个。
      4. 三级缓存+二级缓存检测就是按照这种思路来的,设原对象为A,代理对象为A1,循环依赖对象为B
        1. 第一次获取时,三级缓存里没有东西,所以会创建一个A:getSingleton、doCreateBean,同时将一个FactoryBean放到三级缓存里,准备让B调用
        2. 对A进行属性注入,同时触发循环依赖
        3. B尝试获取A时发现三级缓存里有东西,通过FactoryBean获取对象,而FactoryBean提前启动了AOP后置处理器(getEarlyBeanReference),返回A1,同时将A1放到二级缓存里。
        4. 删除三级缓存,如果其他对象也循环依赖A,就不会重复生成不同的代理对象了。(getEarlyBeanReference可以重复生成代理)
        5. B完成初始化,返回完全可用的对象,A将其拿到并注入自身,此时B保有A1,而A保有B,A1没有B,符合要求。
        6. A的属性注入完成,启动后置处理器链条,由于代理已经执行过了,所以还是返回A
        7. 最后检查二级缓存,发现有一个A1,用A1替换A,返回A1
      5. 可以看到,AOP就是在后置处理器里完成的,没有破坏原有的设计,只不过三级缓存里的FactoryBean会将其提前执行罢了
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值