一文清晰带你弄清楚Spring IOC 循环依赖问题是如何解决的

news/2025/1/12 13:23:38/

什么是循环依赖

循环依赖又被成为循环引用,即两个或者多个bean相互之间的持有对方,比如A 引用B,B引用C,C 又引用A,则它们最终反映为一个环,如下图所示:
在这里插入图片描述
循环依赖是对象之间的相互依赖关系,循环依赖就是一个死循环,除非有终结条件,否则就是死循环,最终导致内存溢出错误.

解决循环依赖

Spring 容器循环依赖包括构造器循环依赖和setter 循环依赖,prototype范围循环依赖.

构造器循环依赖处理

通过构造器注入构成循环依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖,

setter循环或者@Autowired进行循环依赖处理

Spring 的循环依赖的理论依据基于java的引用传递,当获得对象的引用时,对象的属性是可以延后设置,但是构造器必须在获取引用之前.

Spring 通过setxxx 或者@Autowired 方法解决循环依赖其实是通过提前暴露一个ObjectFactory对象来完成,即ClassA 在调用构造器完成对象初始化之后,在调用ClassA 的setClassB方法之前就把ClassA 实例化的对象通过ObjectFactory提前暴露到Spring 容器职工.

Spring 容器初始化ClassA通过构造器初始化对象后提前暴露到Spring 容器.

AbstractAutowireCapableBeanFactory.doCreateBean()方法中提前暴露初始化对象的源代码如下:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

ClassA 调用setClassB方法,Spring 首先尝试从容器获取ClassB ,此时ClassB 不存在Spring容器中,Spring容器初始化B,同时也会将ClassB提前暴露到Spring容器中,ClassB调⽤setClassA⽅法,Spring从容器中获取ClassA ,因为第⼀步中已经提前暴露了ClassA,因此可以获取到ClassA实例.ClassA通过spring容器获取到ClassB,完成了对象初始化操作。这样ClassA和ClassB都完成了对象初始化操作,解决了循环依赖问题。

prototype范围循环依赖处理

对于原型bean的初始化过程中无论是通过构造器参数循环依赖还是通过setter方法产生循环依赖,Spring 都会直接报错处理.
在AbstractBeanFactory.doGetBean()⽅法中是这样对prototype范围循环依赖进行处理的:
在这里插入图片描述
判断是否是prototype循环依赖:
在这里插入图片描述
若是prototype循环依赖直接抛出BeanCurrentlyInCreationException异常:

在这里插入图片描述
当scope="prototype"时,在获取bean之前如果这个原型bean正在被创建则直接抛出异常,原型bean 在创建之前进行标记这个beanName正在被创建,等创建结束之后会被删除标记.
在这里插入图片描述
从源码可以得出这样一个结论: Spring 不支持原型bean的循环依赖.


http://www.ppmy.cn/news/6875.html

相关文章

Java多线程之线程安全问题

文章目录一. 线程安全概述1. 什么是线程安全问题2. 一个存在线程安全问题的程序二. 线程不安全的原因和线程加锁1. 案例分析2. 线程加锁2.1 理解加锁2.2 synchronized的使用2.3 再次分析案例3. 线程不安全的原因三. 线程安全的标准类一. 线程安全概述 1. 什么是线程安全问题 …

SpringBoot 整合 Shiro 实现动态权限加载更新+ Session 共享 + 单点登录

一.说明 二.项目环境 二.编写项目基础类 三.编写Shiro核心类 四.实现权限控制 五.POSTMAN测试 六.项目源码 一.说明 Shiro是一个安全框架,项目中主要用它做认证,授权,加密,以及用户的会话管理,虽然Shiro没有SpringSecurity功能更丰富,但是它轻量,简单,在项目中通常业务…

国内内网穿透市场现状及头部厂商发展路线分析

疫情三年,居家办公是常态,我们不得不远程访问公司内网部署的OA、ERP、CRM、数据库等应用系统,才能顺利完成工作,这一场景把内网穿透这一专业化技术推到普罗大众面前。 内网穿透也叫NAT穿透,又被称为端口映射或内网映射…

html表格-FineReport 配置Oracle外接数据库(1)

1. 概述 1.1 版本 报表服务器版本 功能变更 11.0 - 11.0.3 1)首次配置外接数据库时,支持自行选择是否「迁移数据至要启用的数据库」2)迁移外接数据库的过程提示细化,方便用户了解迁移进度 1.2 功能简介 报表系统配置外接数…

前端食堂技术周刊第 64 期:Node.js 19、Interop 2022、SvelteKit 1.0、2022 Web 性能回顾、最流行的 Node.js

美味值:🌟🌟🌟🌟🌟 口味:冰糖雪梨 食堂技术周刊仓库地址:https://github.com/Geekhyt/weekly 本期摘要 Node.js 19 的新特性Interop 2022 年终更新SvelteKit 1.02022 Web 性能回…

医疗产品设计的新趋势

随着个人健康和医疗数据技术的发展,消费者可以选择更多的方法来跟踪和管理他们的健康状况,因此医疗产品开始转向更多的健康预防领域。医疗器械设计公司认为,随着医疗产品设计从医疗产品转向家庭,医疗产品的设计需要考虑更多的新问…

力扣(LeetCode)1759. 统计同构子字符串的数目(C++)

题目描述 双指针数学 根据同构字符串的定义,还有示例,发现同构子字符串的数量,只和字母相同的区间有关。如abbcccaa,有 444 个影响答案的区间,直观切分为a bb ccc aa,用空格划分区间。遍历的任务就是维护这…

C++ STL 之可变长数组 Vector 详解

文章目录Part.I AttentionChap.I 注意事项Chap.II 操作技巧Part.II FunctionChap.I 构造函数Chap.II 增加函数Chap.III 删除函数Chap.IV 遍历函数Chap.V 判断/大小/其他函数Part.III CodePart.I Attention Chap.I 注意事项 使用vector需要注意的地方: 加引用#inc…