关于Spring中的一级缓存、二级缓存、三级缓存那些事

题记

常常听到别人提起:“一级缓存、二级缓存、三级缓存”。那么它们是什么呢?有什么作用呢?

缓存作用分析

Spring中的一级缓存名为singletonObjects,二级缓存名为earlySingletonObjects,三级缓存名为singletonFactories,除了一级缓存是ConcurrentHashMap之外,二级缓存和三级缓存都是HashMap。它们的定义是在DefaultSingletonBeanRegistry类中。在这里插入图片描述
一级缓存-singletonObjects是用来存放就绪状态的Bean。保存在该缓存中的Bean所实现Aware子接口的方法已经回调完毕,自定义初始化方法已经执行完毕,也经过BeanPostProcessor实现类的postProcessorBeforeInitialization、postProcessorAfterInitialization方法处理;

二级缓存-earlySingletonObjects是用来存放早期曝光的Bean,一般只有处于循环引用状态的Bean才会被保存在该缓存中。保存在该缓存中的Bean所实现Aware子接口的方法还未回调,自定义初始化方法未执行,也未经过BeanPostProcessor实现类的postProcessorBeforeInitialization、postProcessorAfterInitialization方法处理。如果启用了Spring AOP,并且处于切点表达式处理范围之内,那么会被增强,即创建其代理对象。

这里额外提一点,普通Bean被增强(JDK动态代理或CGLIB)的时机是在AbstractAutoProxyCreator实现的BeanPostProcessor的postProcessorAfterInitialization方法中,而处于循环引用状态的Bean被增强的时机是在AbstractAutoProxyCreator实现的SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法中。

三级缓存-singletonFactories是用来存放创建用于获取Bean的工厂类-ObjectFactory实例。在IoC容器中,所有刚被创建出来的Bean,默认都会保存到该缓存中。

Bean在这三个缓存之间的流转顺序为(存在循环引用):

  1. 通过反射创建Bean实例。是单例Bean,并且IoC容器允许Bean之间循环引用,保存到三级缓存中。
  2. 当发生了循环引用时,从三级缓存中取出Bean对应的ObjectFactory实例,调用其getObject方法,来获取早期曝光Bean,从三级缓存中移除,保存到二级缓存中。
  3. Bean初始化完成,生命周期的相关方法执行完毕,保存到一级缓存中,从二级缓存以及三级缓存中移除。

Bean在这三个缓存之间的流转顺序为(没有循环引用):

  1. 通过反射创建Bean实例。是单例Bean,并且IoC容器允许Bean之间循环引用,保存到三级缓存中。
  2. Bean初始化完成,生命周期的相关方法执行完毕,保存到一级缓存中,从二级缓存以及三级缓存中移除。

简略流程图:
在这里插入图片描述

总结

通过以上分析,我们可以得知Bean在一级缓存、二级缓存、三级缓存中的流转顺序为:三级缓存->二级缓存->一级缓存。但是并不是所有Bean都会经历这个过程,例如对于原型Bean(Prototype),IoC容器不会将其保存到任何一个缓存中的,另外即便是单例Bean(Singleton),如果没有循环引用关系,也不会被保存到二级缓存中的。

  • 43
    点赞
  • 150
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Spring框架Bean的缓存是通过三级缓存实现的。其缓存就是指单例Bean的缓存。 当我们首次通过Spring容器获取一个单例Bean时,Spring会先从一级缓存查找是否已经存在该Bean的实例。如果存在,则直接返回该实例;如果不存在,则继续执行后续步骤。 在后续的步骤Spring会尝试从二级缓存获取Bean的实例。二级缓存是一个用于存储原始的Bean定义信息的缓存,它是为了解决循环依赖问题而存在的。如果二级缓存存在Bean的定义信息,则Spring会根据这些信息创建一个新的Bean实例,并放入一级缓存,然后返回该实例。 如果二级缓存不存在Bean的定义信息,或者在创建Bean实例时出现了循环依赖问题,那么Spring会继续执行后续步骤。 在后续步骤Spring会尝试从三级缓存获取Bean的实例。三级缓存是一个用于存储已经创建但是尚未初始化完成的Bean实例的缓存。如果三级缓存存在Bean的实例,则Spring会使用这个实例,并将其放入一级缓存,然后返回该实例。 如果三级缓存不存在Bean的实例,或者在初始化Bean实例时出现了异常,那么Spring会继续执行后续步骤。 在后续步骤Spring会根据Bean的定义信息创建一个新的实例,并将其放入一级缓存,然后返回该实例。 总结一下,一级缓存就是用于缓存单例Bean实例的,它是SpringBean缓存机制的第一层。一级缓存的存在可以提高Bean的获取效率,避免重复创建实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值