(二)构造器注入导致的循环依赖问题及解决方案
当使用构造器注入时经常发生循环依赖问题,因此本篇将重点阐述如何解决该问题:
1 循环依赖
问题描述:Bean A依赖B,Bean B依赖A,这种情况下即为循环依赖,如下:
Bean A --> Bean B --> Bean A
导致问题:当存在循环依赖时,Spring将无法决定先创建哪个bean,这种情况下,Spring将产生异常BeanCurrentlyInCreationException。
2 问题复现
定义如下两个Component:
@Component public class E1 { private E2 e2; public E1(E2 e2) { this.e2 = e2; } } @Component public class E2 { private E1 e1; public E2(E1 e1) { this.e1 = e1; } }
当启动SpringBoot应用时就会报循环依赖问题,如下所示:
3 解决方案
方式一:延迟构造
消除循环依赖的方式是通过延迟加载,只需要在任意一个中使用@Lazy即可解决,如下:
@Component
public class E1 {
private E2 e2;
public E1(@Lazy E2 e2) {
this.e2 = e2;
}
}
@Component
public class E2 {
private E1 e1;
public E2(E1 e1) {
this.e1 = e1;
}
}
方式二:使用setter注入
当依赖最终被使用时再进行注入是最佳的一种方式,同时这也是Spring最推荐的一种方式,如下:
@Component public class E1 { private E2 e2; public void setE2(E2 e2) { this.e2 = e2; } } @Component public class E2 { private E1 e1; public void setE1(E1 e1) { this.e1 = e1; } }
这里需要说明的是:处理循环依赖有很多种方式。我们在处理循环依赖时,首先应该考虑的是是否能够通过重新设计依赖来避免循环依赖并且我们能否接受因重新设计导致的时间成本。如果成本很高或者我们确实需要循环依赖,那么可以使用本文提到的方式来解决循环依赖问题,并且推荐优先考虑使用setter方式。
有疑问欢迎留言