现象
代码语言:javascript复制在Spring处理不了循环依赖的情况下,
会发生异常:
BeanCurrentlyInCreationException: Error creating bean
with name 'mvcResourceUrlProvider':
Requested bean is currently in creation:
Is there an unresolvable circular reference?
原因
虽然Spring利用三级缓存解决了部分循环依赖 问题,但是在构造函数注入的情况下不会很好 的解决: If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario. The Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException. https://docs.spring.io/spring-framework/docs/6.0.x/reference/pdf/core.pdf 解决
- 重新设计依赖,去除循环依赖相关的设计
听说SpringBoot 2.6.x默认禁止我们循环依赖。不过临时提供了一个选项,可以关闭:
代码语言:javascript复制spring:
main:
allow-circular-references: true
- 使用注解@Lazy,注入时
例如:
- 属性注入时和@Autowired注解一起使用
@Lazy
@Autowired
private MyBean myBean;
构造器注入时
代码语言:javascript复制@Component
public class MyBean {
private MyBean2 myBean2;
@Autowired
public MyBean(@Lazy MyBean2 myBean2) {
this.myBean2 = myBean2;
}
}
使用setter方法注入
如:
代码语言:javascript复制 @Autowired
public void setDao(MyDao dao) {
this.dao = dao;
}
从ApplicationContext获取依赖的bean实例
如:
代码语言:javascript复制@Component
public class MyContextProvider {
@Autowired
private ApplicationContext appContext;
public <T> T getBean(Class<T> beanClass) {
return appContext.getBean(beanClass);
}
public Object getBean(String beanName) {
return appContext.getBean(beanName);
}
}
如果不注入ApplicationContext,也可以实现ApplicationContextAware接口,获取ApplicationContext。
总结
项目中能避免循环依赖的,尽量避免;但有些避免不了了,我们只能采用上面的几种方法规避。