循环依赖问题

一个bean的创建分为如下步骤:

当创建一个简单对象的时候,过程如下:

  • 先从单例池中获取bean,发现无 a
  • 创建 a 的实例
  • 为 a 赋值
  • 把 a 放到单例池中

当创建一个对象并且其中有另外一个对象是就变成了这样:

但是当在B对象中由引用了A对象,就会变成这样:

因为A和B两者相互引用,但是单例池中始终无法创建任一对象,所以会出现死循环。

因此,我们需要添加一个半成品池,先把A初始化出来,放到一个半成品池中。

过程如下:

  • 先从单例池中找A对象,没有则开始创建A对象
  • 实例化A对象,并放入半成品池中
  • 为A对象赋值
  • 赋值时发现引用了B对象 --> 实例化B对象,并放入半成品池中
  • 为B对象赋值
  • 赋值时发现引用了A对象,从单例池中和半成品池中找A对象,并将其赋值
  • 实例化B对象,并放入单例池中
  • 实例化A对象,从半成品池中移除A对象,并放入单例池中

这样就解决了死循环创建但是当使用了动态代理后,情况又会有所变化.

先来看一下AOP的执行过程,如图:

在bean的创建过程中,创建动态代理的时机是在初始化之后的,如图:

这个时候半成品池里放的是没有代理过的A对象,当B去半成品池中获取A对象,获取的是动态代理前的A对象,而我们应该获取的是动态代理后的A对象,这就会出现问题.

为了解决AOP的问题,spring又加入了一个工厂池

执行过程如下:

  • 当创建A对象的时候会在工厂池中创建factory(a)
  • ....
  • 当给B赋值时,发现引用了A,就会去工厂池中执行getEarlyReference 提前处理方法,生成一个动态代理后的A对象,并放入半成品池中,再赋值给B
  • ...

注意:

​ 当实例化对象A的时候,A对象会产生与之对应的factory(a)方法,只有当某个对象引用A对象时,factory(a)方法才会被执行,从而去通过提前引用的方式创建动态代理对象放入半成品池中

如果说A对象没有被提前引用,factory(a)方法不会执行

Spring循环依赖问题的解决的更多相关文章

  1. spring循环依赖是怎么解决的?

    回答:循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleA,则它们最终反映为一个环. Spring如何解决循环依赖? ...

  2. Spring循环依赖的三种方式以及解决办法

    一. 什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环.比如A依赖于B,B依赖于C,C又依赖于A.如下图: 注意,这里不是函数的循环调用,是对象的 ...

  3. Spring 循环依赖的三种方式(三级缓存解决Set循环依赖问题)

    本篇文章解决以下问题: [1] . Spring循环依赖指的是什么? [2] . Spring能解决哪种情况的循环依赖?不能解决哪种情况? [3] . Spring能解决的循环依赖原理(三级缓存) 一 ...

  4. Spring循环依赖的解决

    ## Spring循环依赖的解决 ### 什么是循环依赖 循环依赖,是依赖关系形成了一个圆环.比如:A对象有一个属性B,那么这时候我们称之为A依赖B,如果这时候B对象里面有一个属性A.那么这时候A和B ...

  5. Spring循环依赖问题

    什么是循环依赖? 循环依赖就是循环引用,指两个或多个bean互相持有对方,比如说TestA引用TestB.TestB引用TestA,最终形成一个闭环. 注意:循环依赖不是指循环调用. 循环调用:指方法 ...

  6. Spring循环依赖

    Spring-bean的循环依赖以及解决方式 Spring里面Bean的生命周期和循环依赖问题 什么是循环依赖? 循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环. ...

  7. Spring 循环依赖

    循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环.此处不 ...

  8. Springboot源码分析之Spring循环依赖揭秘

    摘要: 若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效.或许刚说到这,有的小伙伴就会大惊失色了.Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就让我 ...

  9. 这个 Spring 循环依赖的坑,90% 以上的人都不知道

    1. 前言 这两天工作遇到了一个挺有意思的Spring循环依赖的问题,但是这个和以往遇到的循环依赖问题都不太一样,隐藏的相当隐蔽,网络上也很少看到有其他人遇到类似的问题.这里权且称他非典型Spring ...

随机推荐

  1. C语言宏的使用

    使用条件宏进行条件编译 譬如,对于同一份代码,我想编译出两个不同的版本,在其中一个版本中去掉某一部分功能, 这时可以通过条件宏判断是否编译,例: 如果不使用条件宏进行控制,想编译两个不同版本的程序,就 ...

  2. concurrentHashMap的put方法详解

    本文主要介绍ConcurrentHashMap的put操作如果有错误的地方欢迎大家指出. 1.ConcurrentHashMap的put操作 ConcurrentHashMap的put操作主要有3种方 ...

  3. iovec结构体使用说明

    http://blog.163.com/lichuan0502@126/blog/static/9933534820111033228285/

  4. java面试-内存分配与回收策略

    1.对象优先在Eden分配 -Xms20M -Xmx20M java堆的大小20M -Xmn10M 新生代10M 老年代10M -XX:SurvivorRatio=8 新生代Eden与一个Surviv ...

  5. 热更新解决方案--tolua学习笔记

    一.tolua使用准备工作:从GitHub上下载tolua(说明:这篇笔记使用的Unity版本是2019.4.18f1c1,使用的tolua是2021年4月9日从GitHub上Clone的tolua工 ...

  6. 201871030106-陈鑫莲 实验二 个人项目-《D{0-1} KP 问题》项目报告

    项目 内容 课程班级博客链接 班级博客 这个作业要求链接 作业要求 我的课程学习目标 1.掌握软件项目个人开发流程2.掌握Github发布软件项目的操作方法 这个作业在哪些方面帮助我实现学习目标 1. ...

  7. 下载kaggle数据集的小妙招

    kaggle是很多数据分析和机器学习初学者非常喜爱的数据科学竞赛平台. 这个平台上有很多接近现实业务场景的数据集,非常适合练手. 今天向大家推荐一个下载kaggle数据集的小工具--kaggleAPI ...

  8. C/C++中的const

    1 C中的const C中const修饰的变量是只读变量,在使用const关键字声明定义变量时会给该变量分配内存空间. const修饰的全局变量默认是外部链接的,即其它源文件可以直接使用该变量. co ...

  9. Java(25-40)【数据类型转换、运算符、方法入门】

    1.ASCII编码表 0--48 A--65 a--97 2. Unicode万国码 字符'中'为20013 3.算数运算符 double类型的加上int类型结果为double byte short ...

  10. SpringBoot 使用逆向工程 构建Mapper.xml Dao层(持久层) 实体类

    逆向工程 注: 有数据库表即可 第一步为创建数据库表 (可选)使用PowerDesigner设计数据库表,物理模型构建 添加pom.xml 逆向工程生成代码插件 <!--plugin 逆向工程生 ...