如果面试官再问你Spring中的循环依赖怎么解决,就这样告诉他

什么是循环依赖?

当一个bean A 依赖另外一个bean B,并且bean B也依赖于bean A时,就会发生这种情况:

bean A -> bean B -> bean A

当然,中间可能会有其他隐含的bean:

bean A -> bean B -> bean C -> bean E -> bean A

Spring中循环依赖会发生什么?

当Spring上下文加载所有bean时,它会尝试按照他们完成工作所需要的顺序来创建bean。例如,如果我们没有循环依赖,就像下面这样:

bean A -> bean B -> bean C

Spring会先创建bean C,然后创建bean B,并将bean C注入到bean B中,然后创建bean A,并将bean B注入到beanA中。

但是,当循环依赖时,Spring就无法确定首先创建哪个bean了,因为它们相互依赖。这种情况下,Spring将抛出
BeanCurrentlyCreationException。

在Spring中使用构造函数注入时,就可能会发生这种情况;如果你使用其他类型的注入,就不会发生这种情况,因为依赖项将在被需要的时候注入,而不是在上下文加载时注入。

解决方法

重新设计

当你有一个循环一来是,很可能是设计问题时,职责没有很好地分开。你可以尝试重新正确地设计组件。以便它们的层次结构良好,不产生循环依赖。

如果由于遗留代码、无法修改的代码或没有足够的时间重新设计时,你可以尝试下面的方法。

使用@Lazy

解决循环依赖一种简单的方法就是Spring懒惰初始化其中一个bean。也就是说:它没有完全初始化bean,而是创建一个代理,并将其注入到另外一个bean中。被注入的bean只有在第一次需要的时候才会完全创建。示例:

使用Setter/Field注入

最流行的解决方法之一,也是Spring官方提出的,就是使用setter注入。

简单地说,使用setter/field注入,而不是构造函数注入-这确实解决了问题。通过这种方式,Spring创建了bean,但在需要它们之前不会注入依赖项。

这里需要注意的是Field注入会使用反射,所以尽量不要使用Field注入。示例:

使用@PostConstruct

另一种解决方式就是在其中一个bean上使用@PostConstruct注释的方法来设置另外一个依赖。示例:

总结

在 Spring 中有很多方法可以处理循环依赖。首先要考虑的是重新设计你的 bean,这样就不需要循环依赖了:它们通常是可以改进的设计的症状。

但是如果你需要在你的项目中有循环依赖,你可以遵循这里建议的一些解决方法。

首选方法是使用 setter 注入。但是还有其他选择,通常基于阻止Spring管理Bean的初始化和注入,然后自己使用一种或多种策略来完成。

猜你喜欢

转载自blog.csdn.net/u011482647/article/details/117385821