Spring 通过 三级缓存机制 解决了 单例 Bean 的循环依赖问题 ,但无法处理 构造器注入的循环依赖 。其核心思想是 提前暴露半成品 Bean 的引用 ,并通过 工厂对象(ObjectFactory) 动态生成代理对象,从而避免循环链条的无限递归。
🧠 一、Spring 循环依赖的定义与限制
✅ 1. 循环依赖的定义
当两个或多个 Bean 相互依赖,形成一个闭环,称为 循环依赖(Circular Dependency)。
示例:
java
@Component
class A {
@Autowired
private B b;
}
@Component
class B {
@Autowired
private A a;
}
✅ 2. Spring 能解决的循环依赖类型
类型 | 是否支持 | 说明 |
---|---|---|
字段/Setter 注入 | ✅ | 支持,使用三级缓存机制 |
构造器注入 | ❌ | 不支持,构造器注入需在实例化时完成依赖注入 |
多例(prototype)Bean | ❌ | 不支持,Spring 无法管理多例 Bean 的生命周期 |
🔄 二、Spring 三级缓存机制详解
Spring 使用 三级缓存 来管理单例 Bean 的创建过程,确保在依赖注入时能获取到"早期引用",从而打破循环依赖。
📦 1. 三级缓存的结构
Spring 使用 DefaultSingletonBeanRegistry
类中的三个 Map 实现三级缓存:
缓存层级 | 类型 | 作用 |
---|---|---|
一级缓存(singletonObjects) | Map<String, Object> |
存放完全初始化完成的 Bean(可直接使用) |
二级缓存(earlySingletonObjects) | Map<String, Object> |
存放提前暴露的"半成品 Bean"(已实例化,但未完成属性注入和初始化) |
三级缓存(singletonFactories) | Map<String, ObjectFactory<?>> |
存放生成 Bean 的工厂对象(用于生成代理对象) |
🧱 三、Spring 创建 Bean 的流程与三级缓存的协作
Spring 创建单例 Bean 的核心流程如下:
1. 实例化 Bean(构造函数调用)
2. 将 Bean 工厂对象加入三级缓存(singletonFactories)
3. 填充属性(依赖注入)
- 如果依赖的 Bean 尚未创建,则触发其创建流程
4. 初始化 Bean(调用 Aware、BeanPostProcessor、初始化方法)
5. 将 Bean 升级到一级缓存(singletonObjects)
✅ 1. 实例化 Bean
调用构造函数创建 Bean 实例,此时 Bean 是"半成品",还未注入属性和初始化。
java
// AbstractAutowireCapableBeanFactory.java
protected Object createBeanInstance(...) {
return getInstantiationStrategy().instantiate(...);
}
✅ 2. 将 Bean 工厂对象加入三级缓存
在实例化后,Spring 会将一个 ObjectFactory
放入三级缓存中,用于后续代理对象的生成。
java
// DefaultSingletonBeanRegistry.java
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory); // 放入三级缓存
}
}
✅ 3. 填充属性(依赖注入)
在填充属性时,如果发现某个依赖的 Bean 还未创建,则会递归调用 getBean()
方法,尝试获取该 Bean。
java
// AbstractAutowireCapableBeanFactory.java
protected void populateBean(...) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
PropertyValues pvsToUse = ((InstantiationAwareBeanPostProcessor) bp).postProcessProperties(...);
applyPropertyValues(beanName, mbd, bw, pvsToUse);
}
}
}
如果依赖的 Bean 还未完全初始化:
- Spring 会调用
getSingleton(String beanName)
方法,尝试从缓存中获取 Bean。 - 如果一级缓存没有,就尝试从二级缓存获取。
- 如果二级缓存也没有,就从三级缓存中获取
ObjectFactory
,调用getObject()
生成 Bean 引用。
java
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject(); // 生成早期引用
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
return singletonObject;
}
✅ 4. 初始化 Bean(调用 Aware、BeanPostProcessor、初始化方法)
初始化阶段包括:
- 调用
BeanNameAware
、BeanFactoryAware
等接口 - 执行
BeanPostProcessor.postProcessBeforeInitialization()
- 调用
@PostConstruct
、InitializingBean.afterPropertiesSet()
、自定义init-method
- 执行
BeanPostProcessor.postProcessAfterInitialization()
java
// AbstractAutowireCapableBeanFactory.java
protected Object initializeBean(...) {
invokeAwareMethods(beanName, wrappedBean); // 调用 Aware 接口
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); // 前置处理器
invokeInitMethods(beanName, wrappedBean, mbd); // 初始化方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); // 后置处理器
return wrappedBean;
}
✅ 5. 将 Bean 升级到一级缓存
在 Bean 完全初始化完成后,将其从三级缓存中移除,放入一级缓存中,供后续使用。
java
// DefaultSingletonBeanRegistry.java
protected void addSingleton(String beanName, Object singletonObject) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
}
🧩 四、AOP 代理的处理(结合三级缓存)
如果 Bean 需要 AOP 代理,Spring 会在 BeanPostProcessor.postProcessAfterInitialization()
中生成代理对象。
java
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null && !containsSingletonCandidate(beanName)) {
return wrapIfNecessary(bean, beanName, new NullSourceClass());
}
return bean;
}
生成代理的过程会调用 AbstractAutoProxyCreator.getProxy()
,最终生成一个代理对象。
这个代理对象会被缓存到 三级缓存 中,供其他 Bean 依赖注入时使用。
❗ 五、Spring 解决循环依赖的前提条件
条件 | 说明 |
---|---|
单例 Bean | Spring 只能解决单例作用域 Bean 的循环依赖 |
Setter/字段注入 | 支持,因为依赖注入发生在属性填充阶段 |
构造器注入 | ❌ 不支持,构造器注入需在实例化时完成依赖注入 |
非代理对象 | 如果 Bean 需要 AOP 代理,代理对象必须通过 ObjectFactory 提前生成 |
✅ 六、总结
特性 | Spring 三级缓存机制 |
---|---|
解决类型 | 单例 Bean、Setter/字段注入的循环依赖 |
不支持类型 | 构造器注入、多例 Bean |
核心机制 | 提前暴露 Bean 的早期引用(半成品 Bean) |
三级缓存结构 | singletonObjects (一级)、earlySingletonObjects (二级)、singletonFactories (三级) |
缓存协作流程 | 三级 → 二级 → 一级 |
AOP 代理处理 | 通过 ObjectFactory 动态生成代理对象 |
核心类 | DefaultSingletonBeanRegistry 、AbstractAutowireCapableBeanFactory |
🧪 七、完整流程图(简化版)
createBean(A)
└── 实例化 A(构造函数)
└── addSingletonFactory(A, ObjectFactory)
└── populateBean(A)
└── 依赖注入 b → getBean(B)
└── createBean(B)
└── 实例化 B(构造函数)
└── addSingletonFactory(B, ObjectFactory)
└── populateBean(B)
└── 依赖注入 a → getBean(A)
└── getSingleton(A) → 从三级缓存获取 A 的早期引用
└── initializeBean(B)
└── postProcessAfterInitialization() → AOP 代理(如有)
└── addSingleton(B, proxyB)
└── initializeBean(A)
└── postProcessAfterInitialization() → AOP 代理(如有)
└── addSingleton(A, proxyA)