一、循环依赖概览
1.1 什么是循环依赖?
flowchart LR
A[A 依赖 B] --> B[B 依赖 A]
B --> A
1.2 循环依赖的三种类型
@Component
public class ServiceA {
private final ServiceB serviceB;
@Autowired
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
@Component
public class ServiceA {
@Autowired
private ServiceB serviceB;
}
1.3 Spring 能解决哪些循环依赖?
| 注入方式 | 单例 Bean | 原型 Bean |
|---|
| Setter / 字段注入 | 可以解决 | 无法解决 |
| 构造器注入 | 无法解决 | 无法解决 |
二、三级缓存原理
2.1 三级缓存是什么?
三级缓存定义在 DefaultSingletonBeanRegistry 中,本质是三个 Map:
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
2.2 三个缓存各自的作用
| 缓存 | 名称 | 存放内容 | 作用 |
|---|
| 一级缓存 | singletonObjects | 完整的 Bean(实例化 + 属性注入 + 初始化完成) | 日常 getBean 获取的就是它 |
| 二级缓存 | earlySingletonObjects | 早期的 Bean(已实例化,属性可能未填充完) | 保存从三级缓存创建的早期引用,避免重复创建代理 |
| 三级缓存 | singletonFactories | ObjectFactory(Bean 工厂 lambda) | 延迟生成早期引用,需要时才调用 getObject(),保证 AOP 代理只创建一次 |
2.3 三个缓存的生命周期
flowchart TD
A[Bean 开始创建] --> B[实例化完成<br/>调用构造器]
B --> C[存入三级缓存<br/>singletonFactories]
C --> D[其他 Bean 引用本 Bean]
D --> E[从三级缓存获取<br/>调用 ObjectFactory.getObject]
E --> F[存入二级缓存<br/>earlySingletonObjects]
F --> G[从三级缓存移除]
G --> H[本 Bean 属性填充 + 初始化完成]
H --> I[存入一级缓存<br/>singletonObjects]
I --> J[从二级缓存移除]
三、Setter 注入解决全流程
3.1 经典场景:A → B → A
@Component
public class A {
@Autowired
private B b;
}
@Component
public class B {
@Autowired
private A a;
}
3.2 完整流程图
sequenceDiagram
participant Client
participant Container as Spring 容器
participant L1 as 一级缓存
participant L2 as 二级缓存
participant L3 as 三级缓存
Client->>Container: getBean("a")
Container->>L1: 检查一级缓存
L1-->>Container: null
Container->>Container: 标记 A 正在创建
Container->>Container: 实例化 A(new A)
Container->>L3: 将 A 的 ObjectFactory 存入三级缓存
Container->>Container: 属性填充:发现需要 B
Container->>Container: getBean("b")
Container->>L1: 检查一级缓存
L1-->>Container: null
Container->>Container: 标记 B 正在创建
Container->>Container: 实例化 B(new B)
Container->>L3: 将 B 的 ObjectFactory 存入三级缓存
Container->>Container: 属性填充:发现需要 A
Container->>Container: getBean("a") 第二次
Container->>L1: 检查一级缓存
L1-->>Container: null
Container->>Container: 检查 A 是否正在创建?是
Container->>L2: 检查二级缓存
L2-->>Container: null
Container->>L3: 检查三级缓存
L3-->>Container: 找到 A 的 ObjectFactory
Container->>Container: 调用 getObject() 获取 A 的早期引用
Container->>L2: 将 A 的早期引用存入二级缓存
Container->>L3: 从三级缓存移除 A
Container-->>Container: 返回 A 的早期引用给 B
Container->>Container: B 属性填充完成
Container->>Container: B 初始化完成
Container->>L1: 将 B 存入一级缓存
Container->>L2: 从二级缓存移除 B
Container-->>Container: B 创建完成,注入到 A
Container->>Container: A 属性填充完成
Container->>Container: A 初始化完成
Container->>L1: 将 A 存入一级缓存
Container->>L2: 从二级缓存移除 A
Container-->>Client: 返回 A
3.3 关键源码:getSingleton() — 三级缓存查找
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
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;
}
3.4 关键源码:doCreateBean() — 暴露到三级缓存
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences
&& isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
3.5 关键源码:addSingletonFactory()
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);
}
}
}
3.6 完整流程简述
四、为什么是三级而非二级
4.1 核心原因:支持 AOP 代理延迟创建
4.2 对比分析
flowchart TD
subgraph 二级缓存方案
A2[实例化 A] --> B2[立即创建代理对象]
B2 --> C2[代理对象存入二级缓存]
C2 --> D2{是否发生循环依赖?}
D2 -->|是| E2[正常,代理被使用]
D2 -->|否| F2[代理被创建但从未使用<br/>浪费性能 + 代理对象不对]
end
subgraph 三级缓存方案[三级缓存方案]
A3[实例化 A] --> B3[ObjectFactory 存入三级缓存]
B3 --> C3{是否发生循环依赖?}
C3 -->|是| D3[调用 getObject 创建代理<br/>存入二级缓存]
C3 -->|否| E3[三级缓存不调用<br/>代理在正常阶段创建]
E3 --> F3[初始化后 AOP 创建代理<br/>BeanPostProcessor]
end
4.3 关键源码:getEarlyBeanReference()
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
4.4 总结
| 问题 | 二级缓存 | 三级缓存 |
|---|
| 能否解决无 AOP 的循环依赖 | | |
| 能否解决有 AOP 的循环依赖 | 代理创建时机不对 | 按需延迟创建 |
| 无循环依赖时是否多余创建代理 | 会提前创建 | 不会 |
| 设计理念 | 简单直接 | 延迟加载,按需创建 |
五、构造器注入为何无法解决
5.1 核心原因:鸡生蛋问题
flowchart TD
A[创建 A] --> B{需要 B 的构造器参数}
B --> C[去创建 B]
C --> D{需要 A 的构造器参数}
D --> E[去创建 A]
E --> F{A 正在创建中!}
F --> G[抛出 BeanCurrentlyInCreationException]
5.2 源码层面的原因
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(bd, beanName);
}
5.3 构造器循环依赖的报错信息
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name
Requested bean is currently in creation: Is there an unresolvable circular reference?
六、特殊场景分析
6.1 @Lazy 解决构造器循环依赖
@Component
public class ServiceA {
private final ServiceB serviceB;
@Autowired
public ServiceA(@Lazy ServiceB serviceB) {
this.serviceB = serviceB;
}
}
@Component
public class ServiceB {
private final ServiceA serviceA;
@Autowired
public ServiceB(@Lazy ServiceA serviceA) {
this.serviceA = serviceA;
}
}
6.2 @Async 导致循环依赖失败
@Component
public class ServiceA {
@Autowired
private ServiceB serviceB;
}
@Component
public class ServiceB {
@Lazy
@Autowired
private ServiceA serviceA;
@Async
public void asyncMethod() { }
}
6.3 原型 Bean 的循环依赖
@Component
@Scope("prototype")
public class ServiceA {
@Autowired
private ServiceB serviceB;
}
@Component
@Scope("prototype")
public class ServiceB {
@Autowired
private ServiceA serviceA;
}
6.4 Spring Boot 2.6+ 默认禁止循环依赖
Spring Boot 2.6 起默认禁止循环依赖:
spring:
main:
allow-circular-references: false
6.5 三种消除循环依赖的设计方案
flowchart TD
A[循环依赖 A->B->A] --> B{如何消除?}
B --> C[方案1: 提取公共逻辑]
B --> D[方案2: 事件驱动解耦]
B --> E[方案3: 中间人模式]
C --> C1[抽取 AB 共用逻辑到 ServiceC<br/>A->C, B->C]
D --> D1[A 发布事件, B 事件<br/>无需互相持有引用]
E --> E1[引入 Manager/Coordinator<br/>A->Manager, B->Manager]
| 方案 | 适用场景 | 示例 |
|---|
| 提取公共逻辑 | A 和 B 需要相同功能 | 抽取 ServiceC,A/B 都依赖 C |
| 事件驱动 | A 完成后通知 B | A 发布 ApplicationEvent,B 用 @EventListener |
| 中间人模式 | A 和 B 需要协调 | 引入 OrderService 协调 PaymentService 和 InventoryService |
七、自检
Q1: 什么是循环依赖?Spring 能解决哪些?
Q2: 三级缓存分别是什么?
Q3: 为什么需要三级缓存?二级不行吗?
Q4: 构造器注入的循环依赖为什么无法解决?
Q5: @Lazy 如何解决构造器循环依赖?
核心源码路径速查:
| 类 | 方法 | 作用 |
|---|
DefaultSingletonBeanRegistry | getSingleton(String, boolean) | 三级缓存查找逻辑 |
DefaultSingletonBeanRegistry | addSingletonFactory() | 存入三级缓存 |
DefaultSingletonBeanRegistry | addSingleton() | 存入一级缓存 |
AbstractAutowireCapableBeanFactory | doCreateBean() | 暴露三级缓存的入口 |
AbstractAutowireCapableBeanFactory | getEarlyBeanReference() | 三级缓存的 ObjectFactory 执行逻辑 |