day06-springBean循环依赖

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

什么是循环依赖?

在我们的开发中,会不可避免的遇到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是通过三级缓存来实现的



相关文章
|
7月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
缓存 Java Spring
Spring框架(四) 三级缓存与循环依赖
首先我们需要明白什么是循环依赖 , 打个比方 , 就是说A对象在创建的过程中 , 需要依赖注入B对象 , 但是B对象没有 , 就需要去创建 , 而在创建B对象的过程中又需要注入A对象 , A对象此时还在创建中,所以就构成了一个死循环 , A,B相互依赖 这样的关系被成为循环依赖(当然 , 可能还会有其他的情况),下面我们就来看看Spring是如何让解决循环依赖的
160 0
|
缓存 Java Spring
【Spring使用三级缓存解决循环依赖的过程】
【Spring使用三级缓存解决循环依赖的过程】
|
7月前
springBean注入循环解决
springBean注入循环解决
|
5月前
|
传感器
循环依赖问题之Bean循环依赖的定义是什么
循环依赖问题之Bean循环依赖的定义是什么
循环依赖问题之Bean循环依赖的定义是什么
|
5月前
|
Java Spring
Spring循环依赖问题之构造器内的循环依赖如何解决
Spring循环依赖问题之构造器内的循环依赖如何解决
|
5月前
|
Java Spring 容器
循环依赖问题之实例化Bean是通过如何实现的
循环依赖问题之实例化Bean是通过如何实现的
|
5月前
|
存储 缓存 Java
Spring循环依赖问题之循环依赖异常如何解决
Spring循环依赖问题之循环依赖异常如何解决
|
7月前
|
缓存 Java 网络架构
从简入繁介绍springbean的循环依赖
【4月更文挑战第11天】Spring Bean的循环依赖是Spring框架中一个比较复杂且有趣的话题,涉及到Spring的核心容器、Bean生命周期和依赖注入机制。我将从简入繁地介绍这一概念,确保即使是初学者也能理解。
58 1
|
7月前
|
存储 缓存 Java
ioc循环依赖怎么解决
ioc循环依赖怎么解决
75 0