什么是循环依赖?

简介: 什么是循环依赖?

什么是循环依赖?

在我们的开发中,会不可避免的遇到Bean之间循环依赖的,所谓循环依赖,就是两个或者两个以上的Bean互相持有对方,这样在程序运行调用中,会出现这种循环依赖的现象,其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。

Spring中循环依赖场景有:
(1)构造器的循环依赖
(2)field属性的循环依赖。

Spring怎么解决循环依赖

从bean初始化步骤我们可以知道,循环依赖主要发生在构造器循环依赖和field循环依赖。

那么我们要解决循环引用也应该从初始化过程着手,对于单例来说,在Spring容器整个生命周期内,有且只有一个对象,所以很容易想到这个对象应该存在Cache中,Spring为了解决单例的循环依赖问题,使用了三级缓存。

singletonObjects:第一级缓存,里面放置的是实例化好的单例对象;

earlySingletonObjects:第二级缓存,里面存放的是提前曝光的单例对象;

singletonFactories:第三级缓存,里面存放的是要被实例化的对象的对象工厂。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // Quick check for existing instance without full singleton lock
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                        synchronized (this.singletonObjects) {
                                // Consistent creation of early reference within full singleton lock
                                singletonObject = this.singletonObjects.get(beanName);
                                if (singletonObject == null) {
                                        singletonObject = this.earlySingletonObjects.get(beanName);
                                        if (singletonObject == null) {
                                                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                                                if (singletonFactory != null) {
                                                        singletonObject = singletonFactory.getObject();
                                                        this.earlySingletonObjects.put(beanName, singletonObject);
                                                        this.singletonFactories.remove(beanName);
                                                }
                                        }
                                }
                        }
                }
        }
        return singletonObject;
}

getSingleton方法的大概处理过程为:

1 判断singletonObjects单例池中是否存在,存在则返回
2 不存在则判断earlySingletonObjects缓存中是否存在,存在则返回
3 不存在则判断singletonFactories缓存中是否存在,不存在则返回null
4 存在则通过该存储工厂创建出最终的bean
5 将该bean加入earlySingletonObjects缓存并从singletonFactories缓存中中移除

总结

当一个Bean调用构造函数进行实例化后,即使属性还未填充,就可以通过三级缓存向外暴露依赖的引用值(所以循环依赖问题的解决也是基于Java的引用传递),这也说明了另外一点,基于构造函数的注入,如果有循环依赖,Spring是不能够解决的。还要说明一点,Spring默认的Bean Scope是单例的,而三级缓存中都包含singleton,可见是对于单例Bean之间的循环依赖的解决,Spring是通过三级缓存来实现的

相关文章
|
1月前
|
设计模式 测试技术 编译器
C++项目中打破循环依赖的锁链:实用方法大全(一)
C++项目中打破循环依赖的锁链:实用方法大全
79 0
|
15天前
|
缓存 Java 网络架构
从简入繁介绍springbean的循环依赖
【4月更文挑战第11天】Spring Bean的循环依赖是Spring框架中一个比较复杂且有趣的话题,涉及到Spring的核心容器、Bean生命周期和依赖注入机制。我将从简入繁地介绍这一概念,确保即使是初学者也能理解。
22 1
|
1月前
|
设计模式 敏捷开发 持续交付
C++项目中打破循环依赖的锁链:实用方法大全(三)
C++项目中打破循环依赖的锁链:实用方法大全
52 0
|
1月前
|
测试技术 持续交付 API
C++项目中打破循环依赖的锁链:实用方法大全(二)
C++项目中打破循环依赖的锁链:实用方法大全
58 0
|
1月前
|
Java 测试技术 Spring
什么是循环依赖,如何解决
什么是循环依赖,如何解决
|
1月前
|
Java 测试技术 Spring
什么是循环依赖,如何解决?
在 Spring 应用中,循环依赖指的是两个或多个 Bean 之间相互引用,造成了一个环状的依赖关系。举例来说,如果 Bean A 依赖于 Bean B,同时 Bean B 也依赖于 Bean A,就形成了循环依赖。这种情况下,Spring 容器在创建这些 Bean 时会陷入无限循环,导致应用启动失败或者出现其他不可预测的问题。
34 1
|
2月前
|
Java 测试技术 Spring
什么是循环依赖,并如何解决
在 Spring 应用中,循环依赖指的是两个或多个 Bean 之间相互引用,造成了一个环状的依赖关系。举例来说,如果 Bean A 依赖于 Bean B,同时 Bean B 也依赖于 Bean A,就形成了循环依赖。这种情况下,Spring 容器在创建这些 Bean 时会陷入无限循环,导致应用启动失败或者出现其他不可预测的问题。
39 0
|
1月前
|
Java 测试技术 开发者
循环依赖:解析软件设计的迷局
循环依赖:解析软件设计的迷局
|
3月前
|
存储 缓存 Java
ioc循环依赖怎么解决
ioc循环依赖怎么解决
31 0
|
5月前
|
XML 缓存 Java
循环依赖和三级缓存原来是这么回事
我们都知道,Spring可以通过三级缓存解决循环依赖的问题,这也是面试中很常见的一个面试题,本文就来着重讨论一下有关循环依赖和三级缓存的问题。