Spring中的循环依赖问题

目录

1、什么是Spring的循环依赖?

2、如何避免循环依赖问题?

3、Spring的三级缓存

小结


1、什么是Spring的循环依赖?

Spring框架中的循环依赖问题是指两个或多个bean之间相互依赖,形成闭环,导致无法完成实例化的问题。简单来说,就是A依赖于B,而B又依赖于A,形成了一个循环的依赖链。

循环依赖问题可能导致应用程序启动失败或者产生不可预期的行为。这是因为当Spring容器创建Bean时,会使用默认的构造函数或Setter方法将依赖注入到Bean中。如果存在循环依赖,那么容器无法确定先创建哪个Bean,从而导致无法完成依赖注入。

⭐扩展:Bean的创建过程:

图片来源:深谈Spring如何解决Bean的循环依赖

在Spring中,循环依赖主要分为两种类型:构造器的循环依赖和field属性的循环依赖。

2、如何避免循环依赖问题?

首先需要明确的一点是,Spring 并不能解决所有循环依赖的问题。Spring提供了以下几种解决循环依赖问题的方式:

1. 构造器注入:Spring容器在创建bean时,会先创建所有没有依赖关系的bean,然后再创建有依赖关系的bean。在创建有依赖关系的bean时,Spring会先创建构造器参数中所需要的bean,然后再创建当前bean。使用构造函数注入代替Setter方法注入,可以确保在创建Bean时所有的依赖都已经提供,这种方式可以解决大部分的循环依赖问题。

2. 使用setter方法注入依赖:在这种情况下,Spring容器可以在实例化bean后通过调用setter方法来注入所需的依赖。

3. 使用@Lazy注解:@Lazy注解可以延迟加载bean的实例化。通过将Bean设置为延迟加载,当需要使用该bean时才会进行实例化。这种方式可以解决部分的循环依赖问题。

4. 使用@Autowired注解搭配@Qualifier注解明确指定依赖关系。通过使用@Qualifier注解,可以明确指定依赖的Bean名称,从而帮助Spring容器正确解析循环依赖。

5. 使用@PostConstruct注解和InitializingBean接口。这两种方式可以在Bean创建完成后执行特定的初始化操作,可以在初始化方法中处理循环依赖的情况。

6. 使用代理:在这种情况下,可以使用AOP代理来实现bean之间的依赖关系。这样,就可以在编译时就解决循环依赖问题。

图片来源:https://www.cnblogs.com/mghio/p/15024461.html

3、Spring的三级缓存

在Spring中,Bean的创建过程中涉及到三级缓存(三级缓存是在Spring 4.x之前的版本中使用的机制):

  1. singletonObjects:这是一级缓存,用于存储完全初始化并准备好的单例Bean实例。这些Bean实例是最终被返回的单例Bean实例。在缓存中,Bean的名字和Bean实例是以键值对的形式存在的。当Bean的依赖注入完成并且初始化后,它会被放置在这个缓存中。

  2. earlySingletonObjects:这是二级缓存,用于存放已经创建,但还未完成初始化的单例Bean实例。这些Bean实例通常是因为依赖其他Bean实例而无法完成初始化,处于不完整状态。在Bean的初始化过程中,如果发现循环依赖,则会将尚未完全初始化的Bean放置在这个缓存中,以便解决循环依赖问题。

  3. singletonFactories:这是三级缓存,用于存储用于创建单例Bean的ObjectFactory工厂对象,这些工厂对象可以用来创建单例Bean实例。当Spring正在创建一个Bean时,如果发现了循环依赖,则会将该Bean的创建工厂放置在这个缓存中,在需要时可以通过该工厂来获取Bean的实例。

图片来源:Spring 的循环依赖问题 - mghio - 博客园

当两个相互依赖的Bean需要被实例化时,Spring会先查看第一级缓存中是否已经有完整的Bean实例。如果有,就使用已有的实例;如果没有,则进入第二级缓存查看是否有已经创建但未初始化的Bean实例。如果有,就使用这个未初始化的Bean实例去初始化另一个Bean,然后再将这个未初始化的Bean实例存入第一级缓存;如果没有,则进入第三级缓存查看是否有可以用来创建Bean实例的工厂对象。如果有,就使用这个工厂对象去创建Bean实例,然后再将这个新创建的Bean实例存入第一级缓存;如果没有,则直接创建新的Bean实例存入第一级缓存。

通过三级缓存机制,Spring可以在循环依赖的情况下正确地初始化每个Bean,避免了出现错误或异常。同时,三级缓存也有效地减少了不必要的重复初始化操作,提高了应用程序的性能。

这三级缓存的使用可以帮助Spring容器在处理循环依赖时能够正确地获取到Bean的实例,并最终完成整个Bean的创建和初始化过程。在Spring 5.x及更新的版本中,已经不再使用三级缓存,而是采用了更加高效和可靠的解决方案来处理循环依赖的问题。

小结

需要注意的是,尽管Spring提供了一些机制来解决循环依赖问题,但是最好的做法仍然是尽量减少组件之间的相互依赖,尽量保持低耦合的设计,从而避免出现循环依赖的情况。良好的设计和架构能够减少循环依赖的发生,提高应用程序的可维护性和可测试性。

参考:

Spring 的循环依赖问题 - mghio - 博客园

深谈Spring如何解决Bean的循环依赖

今天一定要搞清楚Spring如何解决循环依赖

Spring 循环依赖解决方案_spring解决循环依赖-CSDN博客


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/175033.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【力扣】907.子数组的最小值之和

【力扣】907.子数组的最小值之和 文章目录 【力扣】907.子数组的最小值之和1. 题目介绍2. 解法2.1 方法一:单调栈2.2 方法二:动态规划 3. Danger参考 1. 题目介绍 给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr …

ubuntu虚拟机设置跳不出来

前几天在使用ubuntu虚拟机的时候不知道哪一步出错了,导致右上角的设置按钮失效了,怎么点设置界面都出不来。 上网查阅后,有人说是显示器的原因,但是我点设置再点左上角activity并没有显示有设置窗口。 最后找到了解决办法&#xf…

【刷题笔记】分糖果||数组||暴力通过||符合思维方式||多案例分析

分发糖果 文章目录 分发糖果1 题目描述2 题目分析2.1 寻找波峰波谷2.2 从波底往波峰攀爬!2.2 计算糖果 3 代码附录1 1 题目描述 https://leetcode.cn/problems/candy/ n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&…

Unity性能优化技巧篇

资源导入优化 随着项目越来越大,资源越来越多,有一套资源导入自动化设置很有必要,它不但可以减少你的工作量,也能更好的统一管理资源,保证资源的导入设置最优,还不会出错。 AssetPostprocessor 在Unity中…

Mo0n(月亮) MCGS触摸屏在野0day利用,强制卡死锁屏

项目:https://github.com/MartinxMax/Mo0n 后面还会不会在,我可就不知道了奥…还不收藏点赞关注 扫描存在漏洞的设备 #python3 Mo0n.py -scan 192.168.0.0/24 入侵锁屏 #python3 Mo0n.py -rhost 192.168.0.102 -lock 解锁 #python3 Mo0n.py -rhost 192.168.0.102 -unlock …

【Spring Boot】Swagger的常用注解

在Swagger的开发过程中,我们需要在Controller代码等处添加相应的注解,以便可以提高生成的接口文档的可读性为了解决这些问题,Swagger提供了很多的注解,通过这些注解,我们可以更好更清晰的描述我们的接口,包…

相机内存卡照片删除怎么恢复?没有备份可这样操作

在使用相机时,不小心删除了重要的照片可能是每位摄影爱好者的噩梦。然而,通过一些恢复方法,我们有机会挽救被删除的照片。本文将详细介绍相机内存卡照片删除恢复的方法。 图片来源于网络,如有侵权请告知 如果您误删了相机内存卡中…

项目实战——苍穹外卖(DAY10)

如果之前有改过端口号造成WebSocket无法连接的,可以看本篇文章“来单提醒”前的内容进行解决。 课程内容 Spring Task 订单状态定时处理 WebSocket 来单提醒 客户催单 功能实现:订单状态定时处理、来单提醒和客户催单 订单状态定时处理&#xff1a…

242. 有效的字母异位词

这篇文章会收录到 :算法通关村第十二关-白银挑战字符串经典题目-CSDN博客 242. 有效的字母异位词 描述 : 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t …

11【保姆级】-GO语言的struct

11【保姆级】-GO语言的struct 一、Go的面向对象1.1 说明 二、结构体2.1 结构体和结构体变量(实例)的区别和联系2.2 声明结构体 和 细节说明2.3 结构体在内存中的布局2.4 创建结构体和访问结构体的四种方式 在学习GO语言时: 先建立整体框架,然后再去抠细节…

C语言错误处理之sterror和perror函数以及断言处理方式

目录 前言 sterror函数 perror函数 断言处理方式 前言 在错误处理一中,我们解释了C语言三种处理方式中的错误号处理方式,这一篇我们在基于上一篇的基础上加入了sterror函数与perror函数,以及断言处理方式的内容...... sterror函数 包含…

fastsocket提升nginx CPS性能分析

fastsocket是针对单机网络性能优化,提升单机的cps。 提升现在单机7LB服务的性能,预计cps的性能提升一倍。 内核对nginx的性能瓶颈损耗主要在内核的三把锁。 1. accpet的全局队列的sk_lock锁 2. new_inode中的全局inode_lock锁 3. sock_alloc_file中的…

【每日一题】子数组的最小值之和

文章目录 Tag题目来源题目解读解题思路方法一:贡献法单调栈 写在最后 Tag 【贡献法】【单调栈】【数组】【2023-11-27】 题目来源 907. 子数组的最小值之和 题目解读 计算整数数组的连续子数组中最小值的和。 解题思路 本题朴素的解决思想是求出所有的连续子数组…

小航助学题库蓝桥杯题库stem选拔赛(21年1月)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统(含题库答题软件账号)_程序猿下山的博客-CSDN博客 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统(含题库答题软件账号)_程序猿下山的博客-CSD…

SQL Server:流程控制语言详解

文章目录 一、批处理、脚本和变量局部变量和全局变量1、局部变量2、全局变量 二、顺序、分支和循环结构语句1、程序注释语句2、BEGIN┅END语句块3、IF┅ELSE语句4、CASE语句5、WHILE语句6、BREAK和CONTINUE语句BREAK语句CONTINUE语句 三、程序返回、屏幕显示等语句1、RETURN语句…

Python continue的用法详解与转义字符及用法

Python continue的用法详解 continue 的功能和 break 有点类似,区别是 continue 只是忽略当次循环的剩下语句,接着开始下一次循环,并不会中止循环;而 break 则是完全中止循环本身。 如下程序示范了continue 的用法: # …

工程数学笔记 | 傅里叶级数/变换的本质理解

以下内容纯属个人学习记录,难免有误,欢迎指正~ 引子 虽已工作数宰,但当因为工作的需要再次碰到傅里叶级数/变换相关的知识时是还是难免汗流浃背,读书时的痛苦的回忆涌上心头,果然曾经欠下的总归是要偿还的&#xff0c…

Python基础语法之学习print()函数

Python基础语法之学习print函数 1、代码2、效果 1、代码 print("Hello World") print("Hello World1","Hello World2") print("Hello World1\n","Hello World2") print("Hello World",end" 默认结束符是行号…

传输层协议[精选]

网络: 跨主机通信. 互联网通信: 两点之间的通信路径有无数条. 集线器: 把一根网线差出来两根,但是同一时刻只能有一根线跑.交换机: 组建局域网.路由器: 本质就是将两个局域网连接起来 交换机和路由器之间的区别越来越模糊. 调制解调器: 使用电话线上网的时候,需要将电话线的模…

c++容器详解Vector、deque、list、set、multiset、map、multimap、queue、stcak、Array

容器 数据结构描述实现头文件向量(vector)连续存储的元素<vector>列表(list)由节点组成的双向链表,每个结点包含着一个元素<list>双向队列(deque)连续存储的指向不同元素的指针所组成的数组<deque>集合(set)由节点组成的红黑树,每个节点都包含着一个元素,…