什么是循环依赖(常问)?

在Spring中,循环依赖指的是两个或多个Bean之间相互依赖,形成了一个闭环。例如,Bean A依赖于Bean B,而Bean B又依赖于Bean A。这种情况如果处理不当,会导致在创建这些Bean时出现死锁或异常。

以下是一个简单的例子:

@Component
public class BeanA {
    @Autowired
    private BeanB beanB;
}

@Component
public class BeanB {
    @Autowired
    private BeanA beanA;
}

这种循环依赖在Spring中分为三种情况:

  1. 构造器注入的循环依赖:
    如果两个Bean通过构造器互相依赖,例如:

    public BeanA(BeanB beanB) { this.beanB = beanB; }
    public BeanB(BeanA beanA) { this.beanA = beanA; }
    

    Spring无法解析这种循环依赖,因为在构造Bean时需要立即实例化对方的Bean。这种情况会抛出BeanCurrentlyInCreationException。

  2. Setter或字段注入的循环依赖:
    Spring的默认单例模式下,Setter或字段注入的循环依赖可以通过三级缓存(SingletonFactories)解决。Spring在Bean的初始化过程中,会提前暴露一个尚未完全初始化的Bean代理,从而解决依赖闭环。

  3. Prototype作用域的循环依赖:
    对于Prototype作用域,Spring无法解决循环依赖,因为Prototype的Bean不会被Spring容器缓存,因此无法利用三级缓存。

如何解决循环依赖问题?

  1. 优化设计,避免循环依赖:
    重新审视依赖关系,分解职责,消除不必要的循环依赖。

  2. 使用@Lazy注解:
    标注依赖项为懒加载,避免在Bean初始化时立刻注入。

    @Component
    public class BeanA {
        @Autowired
        @Lazy
        private BeanB beanB;
    }
    
  3. 使用接口拆分:
    如果两个Bean存在紧耦合,可以引入接口或事件机制,降低直接依赖。

  4. 明确指定Bean的初始化顺序:
    使用@DependsOn注解显式声明依赖顺序,但这仅适用于某些特定场景。

总结:
循环依赖是Spring中常见的问题之一,开发者应尽量通过合理的设计避免。同时了解Spring的三级缓存机制,可以帮助解决部分循环依赖问题。

posted @   Eiffelzero  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
历史上的今天:
2022-12-15 1945. 字符串转化后的各位数字之和
点击右上角即可分享
微信分享提示