Spring解决循环依赖问题

这篇具有很好参考价值的文章主要介绍了Spring解决循环依赖问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、什么是循环依赖?


例如,就是A对象依赖了B对象,B对象依赖了A对象。(下面的代码属于属性的循环依赖,也就是初始化阶段的循环依赖,区别与底下构造器的循环依赖

  // A依赖了B
    class A{
        public B b;
    } 

    // B依赖了A
    class B{
        public A a;
    }


    A a = new A();
    B b = new B();

    a.b = b;
    b.a = a;

问题来了:
A Bean创建 ——> 依赖了 B 属性 ——>  触发 B Bean创建 ——>  B 依赖了 A 属性 ——>  需要 A Bean(但A Bean还在创建过程中)

二、怎么解决?使用三级缓存


一级缓存为:singletonObjects; 终态 Bean
二级缓存为:earlySingletonObjects; 临时Bean
三级缓存为:singletonFactories;


/** Cache of singleton objects: bean name –> bean instance */
private final Map singletonObjects = new ConcurrentHashMap(256);

/** Cache of singleton factories: bean name –> ObjectFactory */
private final Map singletonFactories = new HashMap>(16);

/** Cache of early singleton objects: bean name –> bean instance */
private final Map earlySingletonObjects = new HashMap(16);


singletonObjects」中缓存的是已经经历了完整生命周期的bean对象。(用户查询SpringBeanUtil.getBean,也是查一级缓存,因为查二级缓存,可能npe,因为二级缓存的bean是没加载完的,属性可能还没赋值)

earlySingletonObjects」比 singletonObjects 多了一个 early ,表示缓存的是早期的 bean对象。早期指的是 Bean 的生命周期还没走完就把这个 Bean 放入了 earlySingletonObjects。

singletonFactories」中缓存的是 ObjectFactory,表示对象工厂,用来创建某个对象的。
 

Spring解决循环依赖问题,java,开发语言

1、A初始化的时候,需要B,但是B没有,所以创建B,

2、B 创建的时候,需要A,A现在还没完事呢,那么会把A 放到 earlySingletonObjects ,B成功取到 A, B创建成功,B放到 SingletonObjects

3、A 从 SingletonObjects 取到 B,A完成初始化

4、A初始化后,会从 earlySingletonObjects 挪到 SingletonObjects 

————————

上面这个步骤没利用只用到了2级缓存,你会发现 B内部的A属性其实存的是 A的原始对象,不是A的终极对象,也就是有2个A对象,一个位于SingletonObjects ,一个位于 earlySingletonObjects 

————————

三级缓存如何解决这个问题?

1、每个对象在创建的时最开始,都会先把自己丢到 singletonFactories 三级缓存里面去

2、初始化的时候,就是给属性 b 赋值的时候,从三级缓存里面getObject就会给你把 b 对象丢给你,就自始至终都是这个对象

Spring解决循环依赖问题,java,开发语言

3.1 为什么无法解决构造器的循环依赖问题?

 public class A {
        B b;
        public A(B b) {
            this.b = b;
        }
    }


    public class B {
        A a;

        public B(A a) {
            this.a = a;
        }
    }

首先,对象最开始分为两个阶段:实例化阶段(创建阶段) + 初始化阶段 

初始化阶段,主要是给对象内的属性赋值。

实例化阶段,会调用对象的构造函数。

只有实例化后的对象(也就是调用完构造函数后的对象),才会放到三级缓存中去,构造函数是在实例化时调用的,那就无法拿到,没法解决这个问题。文章来源地址https://www.toymoban.com/news/detail-651408.html

到了这里,关于Spring解决循环依赖问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring工程的启动流程?bean的生命周期?提供哪些扩展点?管理事务?解决循环依赖问题的?事务传播行为有哪些?

    Spring工程的启动流程主要包括以下几个步骤: 加载配置文件:Spring会读取配置文件(如XML配置文件或注解配置)来获取应用程序的配置信息。 实例化并初始化IoC容器:Spring会创建并初始化IoC容器,即ApplicationContext。在这一步,Spring会解析配置文件,并将配置的Bean实例化。

    2024年02月12日
    浏览(38)
  • spring 的循环依赖以及spring为什么要用三级缓存解决循环依赖

            bean的生命周期         这里简单过一下 class -无参构造 -普通对象 -依赖注入(对加了autowire等的属性赋值) -初始化前-初始化 -初始化后(aop) -放入单例池的map(一级缓存) -bean对象 这里提一点单例bean单例bean 其实就是用mapbeanName,Bean对象创建的,多例bean就不

    2024年02月15日
    浏览(57)
  • Spring解决循环依赖

    目录 什么是spring循环依赖 什么情况下循环依赖可以被处理? spring 如何解决循环依赖 创建A这个Bean的流程 答疑 疑问:在给B注入的时候为什么要注入一个代理对象? 初始化的时候是对A对象本身进行初始化,而容器中以及注入到B中的都是代理对象,这样不会有问题吗? 三级

    2024年02月22日
    浏览(48)
  • (循环依赖问题)学习spring的第九天

     Bean实例的属性填充  Spring在属性注入时 , 分为如下几种情况 : 注入单向对象引用 : 如usersevice里注入userdao , userdao里没有注入其他属性     注入双向对象引用 : 如usersevice里注入userdao , userdao也注入usersevice属性  (搞清原理即可) 问题提出 : 形成死循环 解决问题 : 三级缓存解决

    2024年01月22日
    浏览(37)
  • 三级缓存---解决 Spring 循环依赖

    首先,什么是循环依赖?这个其实好理解,就是两个 Bean 互相依赖,类似下面这样: \\\"\\\"\\\" \\\"\\\"\\\" AService 和 BService 互相依赖: 一般来说,循环依赖有三种不同的形态,上面就是其中一种。 另外两种分别是三者依赖,如下图: 这种循环依赖一般隐藏比较深,不易发觉。 还有自我依

    2024年02月16日
    浏览(47)
  • Spring 怎么解决循环依赖的呢?

    Spring 循环依赖:简单说就是自己依赖自己,或者和别的 Bean 相互依赖。 只有单例的 Bean 才存在循环依赖的情况, 原型 (Prototype)情况下,Spring 会直接抛出异常。原因很简单,AB 循环依赖,A 实例化的时候,发现依赖 B,创建 B 实例,创建 B 的时候发现需要 A,创建 A1 实例……

    2024年02月09日
    浏览(43)
  • Spring——三级缓存解决循环依赖详解

    就是在Bean生成流程中保存Bean对象三种形态的三个Map集合,如下: 用来解决什么问题? 这个大家应该熟知了,就是循环依赖 什么是循环依赖? 就像下面这样,AService 中注入了BService ,而BService 中又注入了AService ,这就是循环依赖 这几个问题我们结合源码来一起看一下 : 三级

    2024年02月03日
    浏览(42)
  • Spring 能解决所有循环依赖吗?

    以下内容基于 Spring6.0.4。 看了上篇文章的小伙伴,对于 Spring 解决循环依赖的思路应该有一个大致了解了,今天我们再来看一看,按照上篇文章介绍的思路,有哪些循环依赖 Spring 处理不了。 严格来说,其实也不是解决不了,所有问题都有办法解决,只是还需要额外配置,这

    2024年02月17日
    浏览(49)
  • [Spring] 三级缓存解决循环依赖详解

    注册一个bean对象的过程: Spring扫描class得到BeanDefinition – 根据得到的BeanDefinition去生成bean – 现根据class推断构造方法 – 根据推断出来的构造方法,反射,得到一个对象 – 填充初始对象中的属性(依赖注入) – 如果原始对象种的某个方法被AOP了,那么要根据原始对象生成一

    2024年02月15日
    浏览(41)
  • Spring 是如何解决循环依赖的

    1.什么是循环依赖? 所谓的循环依赖是指,A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。或者是 A 依赖 B,B 依赖 C,C 又依赖 A。它们之间的依赖关系如下: 2.通过手写代码演示理解Spring循环依赖 DEMO: 为什么需要二级缓存? 一级缓存和二级缓存相比: 二级缓存只要是为了分

    2024年02月03日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包