1. 循环依赖的本质与Spring处理机制
在Spring框架中,循环依赖指的是两个或多个Bean相互依赖对方完成初始化的情况。比如Bean A的构造需要注入Bean B,而Bean B又需要注入Bean A。这种"鸡生蛋蛋生鸡"的问题在普通场景下会导致无限递归。
Spring通过三级缓存机制巧妙地解决了这个问题:
- 一级缓存(singletonObjects):存放完全初始化好的Bean
- 二级缓存(earlySingletonObjects):存放提前暴露的原始Bean引用
- 三级缓存(singletonFactories):存放Bean工厂对象
当使用AOP代理时,情况会变得复杂。因为AOP需要生成代理对象,而代理对象的创建时机与原始Bean不同,这就形成了特殊的循环依赖场景。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. AOP代理导致的循环依赖问题
假设我们有如下相互依赖的Bean:
java复制@Service
public class ServiceA {
@Autowired
private ServiceB serviceB;
@Async // 需要AOP代理
public void methodA() {...}
}
@Service
public class ServiceB {
@Autowired
private ServiceA serviceA;
}
这里的问题在于:
- Spring开始创建ServiceA原始对象
- 发现需要注入ServiceB
- 开始创建ServiceB,发现需要注入ServiceA
- 此时ServiceA还未完成AOP代理,直接注入原始对象会导致后续代理不一致
3. 解决方案一:调整依赖关系
最根本的解决方法是重构代码,消除循环依赖。常用手段包括:
3.1 提取公共逻辑到第三方类
java复制@Service
public class CommonService {
// 将A和B的公共依赖提取到这里
}
3.2 使用Setter注入替代构造器注入
java复制@Service
public class ServiceA {
private ServiceB servic
