一、构造器注入引发的循环依赖
1. 问题复现
@component
public class servicea {
private final serviceb serviceb;
@autowired
public servicea(serviceb serviceb) { // 构造器注入
this.serviceb = serviceb;
}
}
@component
public class serviceb {
private final servicea servicea;
@autowired
public serviceb(servicea servicea) { // 构造器注入
this.servicea = servicea;
}
}报错信息:requested bean is currently in creation: is there an unresolvable circular reference?
2. 原理分析
- 三级缓存失效:构造器注入要求在实例化阶段完成依赖注入,而此时 bean 尚未放入三级缓存。
- 生命周期冲突:

3. 解决方案
- 方案 1:将其中一个 bean 改为 setter / 字段注入
- 方案 2:使用 `@lazy` 延迟加载
@autowired
public servicea(@lazy serviceb serviceb) {
this.serviceb = serviceb;
}二、原型(prototype)作用域的循环依赖
1. 问题复现
@scope("prototype")
@component
public class prototypea {
@autowired private prototypeb b;
}
@scope("prototype")
@component
public class prototypeb {
@autowired private prototypea a;
}2. 原理分析
缓存机制不生效:原型 bean 不会存入三级缓存,每次请求都创建新实例。
spring 官方限制:明确说明不处理原型 bean 的循环依赖。
3. 解决方案
重构设计:避免原型 bean 之间的循环依赖
改用单例:评估是否真的需要原型作用域
三、@async 注解导致的代理冲突
1. 问题复现
@service
public class asyncservicea {
@autowired private asyncserviceb serviceb;
@async
public void asyncmethod() { /* ... */ }
}
@service
public class asyncserviceb {
@autowired private asyncservicea servicea;
}2. 原理分析
代理时序问题:
@async通过后置处理器生成代理,可能破坏三级缓存机制。典型错误栈:
beancreationexception: error creating bean with name 'asyncservicea': bean with name 'asyncservicea' has been injected into other beans [...] in their raw version as part of a circular reference.
3. 解决方案
- 方案 1:对异步方法所在类使用接口代理
@async
public interface asyncservice {
void asyncmethod();
}
@service
public class asyncserviceimpl implements asyncservice { /* ... */ }- 方案 2:在注入点添加
@lazy
@autowired @lazy private asyncservicea servicea;
四、configuration 类之间的循环依赖
1. 问题复现
@configuration
public class configa {
@autowired private configb configb;
}
@configuration
public class configb {
@autowired private configa configa;
}2. 原理分析
配置类加载顺序:配置类需要优先初始化,无法通过常规循环依赖解决。
spring 限制:
@configuration类被视为特殊 bean,其代理机制与普通 bean 不同。
3. 解决方案
重构配置类:合并相关配置
使用
@dependson:明确指定加载顺序
@configuration
@dependson("configb")
public class configa { /* ... */ }五、自定义 beanpostprocessor 引发的冲突
1. 问题复现
@component
public class customprocessor implements beanpostprocessor {
@autowired private servicex x; // 依赖其他bean
}2. 原理分析
处理器加载时序:
beanpostprocessor需要优先初始化,此时普通 bean 尚未创建。spring 启动流程:

3. 解决方案
避免在 beanpostprocessor 中注入其他 bean
使用延迟注入
private objectprovider<servicex> xprovider;
public object postprocessbeforeinitialization(object bean, string beanname) {
servicex x = xprovider.getifavailable();
// ...
}六、终极解决方案工具箱
| 问题类型 | 应急方案 | 根治方案 |
|---|---|---|
| 构造器循环依赖 | @lazy 注解 | 改为 setter 注入 |
| 原型bean循环依赖 | 重构作用域 | 引入中间类抽象依赖 |
| aop代理冲突 | 接口代理模式 | 调整切面作用顺序 |
| 配置类循环依赖 | @dependson 指定顺序 | 合并配置类 |
| beanpostprocessor依赖 | objectprovider 延迟获取 | 分离处理器与业务逻辑 |
结语:跳出循环依赖的思维陷阱
spring 的循环依赖处理机制体现了框架设计的高度智慧,但作为开发者,最优雅的解决方案往往不是技术手段,而是架构设计。通过以下原则可从根本上避免循环依赖:
单一职责原则:拆分臃肿的 bean
依赖倒置原则:面向接口编程
层次化设计:controller -> service -> repository 的严格分层
以上就是spring无法解决循环依赖的五种场景分析的详细内容,更多关于spring无法解决循环依赖的资料请关注代码网其它相关文章!
发表评论