今天来学习下Spring的三级缓存机制,主要涉及到以下问题
- 三级缓存是为了解决什么问题?
- 二级缓存为什么不行?
- 三级缓存的实现机制
设计动机
Spring的三级缓存机制,主要是为了解决循环依赖问题,蕴含着对对象创建、依赖注入、代理生成等复杂场景的深度权衡。
- 当对象A依赖对象B,对象B反向依赖对象A,传统单线程造成死锁困境
- AOP代理对象在对象初始化完成后,但依赖循环需要提前注入
核心矛盾
- 必须在对象初始化后才能确定是否要生成代理对象
- 循环依赖需要在初始化前完成暴露对象引用
矛盾推演:
- 如果提前生成代理:可能错误生成不需要代理的对象代理逻辑依赖初始化后的状态
- 如果延后生成代理:早期注入的对象与最终对象不一致破坏单例原则
解法演进
三级缓存源码结构
// 核心缓存定义(DefaultSingletonBeanRegistry)
public class DefaultSingletonBeanRegistry ... {// 一级缓存:完整 Bean(成品)private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);// 二级缓存:早期暴露对象(半成品)private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);// 三级缓存:对象工厂(生成半成品的 lambda)private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
}
Bean创建流程与缓存交互
要透彻理解 Spring 的三级缓存机制,我们需要深入源码层面分析其设计哲学。这里以 Spring Framework 5.3.x 的 DefaultSingletonBeanRegistry 源码为核心进行解析。
一、三级缓存源码架构
// 核心缓存定义(DefaultSingletonBeanRegistry)
public class DefaultSingletonBeanRegistry ... {// 一级缓存:完整 Bean(成品)private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);// 二级缓存:早期暴露对象(半成品)private final Map