01-三级缓存的核心目的
Spring 三级缓存主要解决两个核心问题:
- 单例 Bean 的循环依赖问题:Bean A 依赖 Bean B,Bean B 又依赖 Bean A
- AOP代理与循环依赖的兼容问题:在循环依赖场景下,如何确保注入的是正确的代理对象
02-三级缓存的完整定义
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { // 第一级缓存:完全初始化好的单例Bean private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 第二级缓存:提前暴露的单例Bean(已实例化但未完成初始化) private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); // 第三级缓存:单例工厂(用于创建Bean的早期引用,可能包含代理对象) private final Map<String, ObjectFactory<?>> singletonFactories = new ConcurrentHashMap<>(16); // 正在创建中的Bean名称集合 private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); // 已注册的单例Bean名称集合 private final Set<String> registeredSingletons = new LinkedHashSet<>(256); }03-各级缓存详细说明
3.1 一级缓存:singletonObjects
一级缓存存储完全初始化完成的 Bean 实例
特点:
- Bean 已经完成了所有初始化步骤:
- 实例化(调用构造方法)
- 属性填充(@Autowired 注入)
- 初始化(@PostConstruct、InitializingBean)
- 如果有 AOP 代理,存储的是代理对象
- 线程安全,支持并发访问
- 存储的 Bean 可以直接被应用程序使用
3.2二级缓存:earlySingletonObjects
二级缓存存储提前暴露的 Bean 实例(已实例化但未完成属性注入)
特点:
- Bean 已经实例化,但尚未完成属性注入
- 主要是为了解决循环依赖而临时存储
- 如果 Bean 需要 AOP 代理,这里存储的是代理对象
- 从三级缓存的 ObjectFactory 创建后移入二级缓存
3.3 三级缓存:singletonFactories
三级缓存存储ObjectFactory 工厂对象,用于创建 Bean 的早期引用
特点:
- 存储的是
ObjectFactory<?>而不是 Bean 实例 - 调用
getObject()方法可以创建 Bean 的早期引用 - 核心作用:解决 AOP 代理与循环依赖的结合问题
- 在 Bean 实例化后、属性注入前放入
04-三级缓存的关键方法详解
4.1addSingletonFactory():添加三级缓存
将创建 Bean 的工厂放入三级缓存,为循环依赖提供出口
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { // 放入三级缓存 this.singletonFactories.put(beanName, singletonFactory); // 从二级缓存移除(保证数据一致性) this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }4.2 getSingleton():获取单例Bean
涉及所有三级缓存:按 1→2→3 顺序查找
三级缓存的查询逻辑:
protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 快速检查一级缓存(完全初始化的Bean) Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 检查二级缓存(提前暴露的Bean) singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 检查三级缓存(Bean工厂) ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 调用工厂方法获取Bean的早期引用 singletonObject = singletonFactory.getObject(); // 将获取到的Bean放入二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); // 从三级缓存移除 this.singletonFactories.remove(beanName); } } } } return singletonObject; }4.3 getEarlyBeanReference():获取早期Bean引用
从三级缓存 获取工厂时调用,生成早期引用(可能是代理对象)
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; // 如果BeanDefinition不是合成的(非基础设施Bean)且存在InstantiationAwareBeanPostProcessor if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; // 关键:后置处理器可能返回代理对象 exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); } } } return exposedObject; }05-完整流程演示:A ↔ B 循环依赖 + AOP
假设有两个Service,且A需要AOP代理:
@Service @Transactional // A需要事务代理 public class ServiceA { @Autowired private ServiceB serviceB; public void methodA() { // 业务逻辑 } } @Service public class ServiceB { @Autowired private ServiceA serviceA; public void methodB() { // 业务逻辑 } }详细执行流程:
06-注意事项
6.1 构造器注入无法使用三级缓存
构造器调用时对象还未创建,无法放入三级缓存,因此无法解决循环依赖。
@Component public class ServiceA { private final ServiceB serviceB; @Autowired // 构造器注入 public ServiceA(ServiceB serviceB) { this.serviceB = serviceB; // 构造时就依赖B,但B可能还未创建 // 此时ServiceA还未实例化完成,ServiceA 无法放入三级缓存 } }6.2 原型Bean的循环依赖
原型Bean不放入三级缓存,每次请求都创建新实例
@Scope("prototype") @Component public class PrototypeA { @Autowired private PrototypeB b; } @Scope("prototype") @Component public class PrototypeB { @Autowired private PrototypeA a; }Spring会直接抛出异常:BeanCurrentlyInCreationException: Error creating bean with name 'prototypeA': Requested bean is currently in creation
6.3 @Async方法的特殊处理
@Async也是通过AOP实现的,但处理时机不同;
需要在initializeBean阶段创建代理,可能影响循环依赖
@Service public class AsyncService { @Async public void asyncMethod() { // 异步方法 } @Autowired private AnotherService anotherService; }07-总结
| 缓存级别 | 存储内容 | 生命周期 | 主要作用 |
|---|---|---|---|
| 一级缓存 | 完全初始化的Bean | Bean整个生命周期 | 提供最终可用的Bean |
| 二级缓存 | 早期Bean(已实例化未初始化) | 创建过程中临时存在 | 解决循环依赖,避免重复创建 |
| 三级缓存 | ObjectFactory工厂对象 | Bean实例化后到初始化前 | 处理AOP代理,确保返回正确的代理对象 |
核心思想:通过懒加载的ObjectFactory延迟决策,只有在真正发生循环依赖时才创建代理对象,既解决了循环依赖问题,又保持了Bean生命周期的完整性,同时支持AOP等增强功能。