java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring循环依赖

Spring循环依赖​​的解决方式详解

作者:二进制11

这篇文章主要介绍了Spring循环依赖​​的解决方式,​​循环依赖​​是指两个或多个Bean互相依赖,形成闭环,导致Spring无法正常完成依赖注入,需要的朋友可以参考下

什么是循环依赖

循环依赖是指两个或多个Bean相互依赖,形成一个闭环。例如:

@Component
public class A {
    @Autowired
    private B b;
}
@Component
public class B {
    @Autowired
    private A a;
}

在这个例子中,A依赖B,B又依赖A,形成了一个循环依赖链。

Spring解决循环依赖的机制

Spring通过三级缓存机制来解决循环依赖问题,具体实现如下:

三级缓存结构

解决流程

Spring解决循环依赖的核心流程如下:

详细步骤解析

创建Bean A:

发现依赖B:

创建Bean B:

发现依赖A:

完成B的创建:

完成A的创建:

代码层面的实现

Spring解决循环依赖的核心代码在DefaultSingletonBeanRegistry类中:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 首先检查一级缓存
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 检查二级缓存
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 检查三级缓存
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    // 从三级缓存移到二级缓存
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

循环依赖的限制

Spring并非能解决所有类型的循环依赖,有以下限制:

构造器注入:无法解决构造器注入的循环依赖

@Component
public class A {
    private B b;
    @Autowired
    public A(B b) { this.b = b; }
}
@Component
public class B {
    private A a;
    @Autowired
    public B(A a) { this.a = a; }
}

这种情况会抛出BeanCurrentlyInCreationException

原型(prototype)作用域的Bean:Spring不支持原型Bean的循环依赖

@Async方法:如果循环依赖中包含@Async方法,也可能出现问题

最佳实践

@Component
public class A {
    @Lazy
    @Autowired
    private B b;
}

总结

Spring通过三级缓存机制巧妙地解决了setter/field注入方式的循环依赖问题。理解这一机制不仅有助于我们避免开发中的循环依赖陷阱,也能更深入地理解Spring容器的Bean生命周期管理。在实际开发中,我们应当合理设计Bean之间的依赖关系,尽量避免循环依赖,当确实需要时,也要了解其背后的原理和限制。

以上就是Spring循环依赖​​的解决方式详解的详细内容,更多关于Spring循环依赖的资料请关注脚本之家其它相关文章!

阅读全文