详解Spring DI循环依赖实现机制
一个对象引用另一个对象递归注入属性即可实现后续的实例化,同时如果两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环即所谓的循环依赖怎么实现呢属性的互相注入呢?

Spring bean生命周期具体流程如下:

实际与bean实例化及初始化相关的流程如下(单例模式,其他模式不支持循环依赖):


在DefaultSingletonBeanRegistry类中提供获得单例bean的方法getSingleton:

对于Spring循环依赖使用三级缓存实现:一级singletonObjects一级缓存,存储单例对象,Bean 已经实例化,初始化完成;二级earlySingletonObjects,存储 singletonObject,这个 Bean 实例化了,还没有初始化;三级singletonFactories,存储 singletonFactory。
实际上Spring在实例化前提前暴露所有需要实例化的Bean,提供BeanDefinition类专注于保存被识别的bean定义。Spring Bean加载全过程(注解配置) - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中详细描述了BeanDefinitionMap的生产过程。
bean定义都有了就剩下实例化,最复杂的莫过于循环依赖,三级缓存具体业务逻辑如下图:

总结: 1)Spring 不⽀持原型 bean 的循环依赖。
2)单例bean通过setXxx或者@Autowired进⾏循环依赖
Spring 的循环依赖的理论依据基于 Java 的引⽤传递,当获得对象的引⽤时,对象的属性是可以延后设置的,但是构造器必须是在获取引⽤之前。Spring通过setXxx或者@Autowired⽅法解决循环依赖其实是通过提前暴露⼀个ObjectFactory对象来完成的,简单来说ClassA在调⽤构造器完成对象初始化之后,在调⽤ClassA的setClassB⽅法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中。
详解Spring DI循环依赖实现机制的更多相关文章
- 用IDEA详解Spring中的IoC和DI(挺透彻的,点进来看看吧)
用IDEA详解Spring中的IoC和DI 一.Spring IoC的基本概念 控制反转(IoC)是一个比较抽象的概念,它主要用来消减计算机程序的耦合问题,是Spring框架的核心.依赖注入(DI)是 ...
- 使用IDEA详解Spring中依赖注入的类型(上)
使用IDEA详解Spring中依赖注入的类型(上) 在Spring中实现IoC容器的方法是依赖注入,依赖注入的作用是在使用Spring框架创建对象时动态地将其所依赖的对象(例如属性值)注入Bean组件 ...
- [跟我学spring学习笔记][DI循环依赖]
循环依赖 什么是循环依赖? 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方. Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢? ...
- 五、spring之DI循环依赖
什么是循环依赖 循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映 ...
- 【转】详解spring 每个jar的作用
spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar, aspects.jar, spring-portlet.jar, and spring-hibernate2. ...
- 浅谈Spring解决循环依赖的三种方式
引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种: ...
- Java集合详解3:Iterator,fail-fast机制与比较器
Java集合详解3:Iterator,fail-fast机制与比较器 今天我们来探索一下LIterator,fail-fast机制与比较器的源码. 具体代码在我的GitHub中可以找到 https:/ ...
- Spring的循环依赖问题
spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类: 在Spring中将循环依赖的处理分成了3种情况: 构造器循环依赖 ...
- applicationContext.xml详解 spring+mybatis+struts
今天给大家详细解释一项关于Spring的applicationContext.xml文件,这对于初学者来说,应该是很有帮助的, 以下是详解Spring的applicationContext.xml文件 ...
随机推荐
- docker 环境安装 jenkins
下载镜像运行 jenkins 默认服务器已经安装好了 docker 环境: 拉取 jenkins 镜像 docker pull jenkins/jenkins:lts 镜像的详细信息可以查看:http ...
- java 8 - java 17 升级指北
2014年发布的java SE 8和2017年发布的java EE 8,至今还是使用最广泛的java版本,大部分java开发者对于java 8之后的升级总是敬而远之,这跟java 9以后的破坏性升级和 ...
- Pop Sequeue
题目描述 Given a stack which can keep M numbers at most. Push N numbers in the order of 1,2,3...,N and p ...
- 【C primer plus】初始化链表函数的错误
C primer plus第六版 的一处错误 第五百页17.3.4 实现接口的程序清单17.5中的初始化链表函数有误 #源代码 void InitializeList(List * plist) { ...
- Abp vnext EFCore 实现动态上下文DbSet踩坑记
背景 我们在用EFCore框架操作数据库的时候,我们会遇到在 xxDbContext 中要写大量的上下文 DbSet<>; 那我们表少还可以接受,表多的时候每张表都要写一个DbSet, 大 ...
- 【代码分享】用redis+lua实现多个集合取交集并过滤,类似于: select key from set2 where key in (select key from set1) and value>=xxx
redis中的zset结构可以看成一个个包含数值的集合,或者认为是一个关系数据库中用列存储方式存储的一列. 需求 假设我有这样一个数据筛选需求,用SQL表示为: select key from set ...
- golang中int、float、string数据类型之间的转换
package main import ( "fmt" "strconv" ) func main() { var num1 int = 88 var num2 ...
- 请解释final finally finalize的区别
final 关键字 ,可以定义不能被继承的父类.定义不能被重写的方法,常量 finally 关键字, 异常处理的统一出口 不管是否有异常都执行 finalize 方法(protected ...
- 使用Hot Chocolate和.NET 6构建GraphQL应用(4) —— 实现Query映射功能
系列导航 使用Hot Chocolate和.NET 6构建GraphQL应用文章索引 需求 在上一篇文章使用Hot Chocolate和.NET 6构建GraphQL应用(3) -- 实现Query基 ...
- qiankun 2.x 运行时沙箱 源码分析
简介 从源码层面详细讲解了 qiankun 框架中的 JS 沙箱 和 样式沙箱的实现原理. 序言 沙箱 这个词想必大家应该不陌生,即使陌生,读完这篇文章也就不那么陌生了 沙箱 (Sandboxie) ...