Spring学习笔记_21——循环依赖

循环依赖

1. 介绍

在Spring中的循环依赖就是指一个或者多个Bean之间存在着互相依赖的关系,并且形成了循环调用。

例如:在Spring中,Bean-A依赖Bean-B,Bean-B又依赖Bean-A,Bean-A和Bean-B之间就形成了相互依赖的关系。在创建A对象时,发现A对象依赖了B对象,此时先去创建B对象;创建B对象时,发现B对象又依赖了A对象,此时又区创建A对象......形成死循环。

同理,在Spring中多个对象之间有可能存在循环依赖。

2. 循环依赖类型

  • 自我依赖:Bean自己依赖自己,从而形成的循环依赖,一般情况下不会发生这种循环依赖。
  • 直接依赖:一般时发生在两个对象之间,A依赖B、B依赖A
  • 间接依赖:一般是发生在三个或三个以上对象之间互相依赖的场景。A依赖B、B依赖C、C依赖A......

3. 循环依赖场景

  • 构造器循环依赖
    • 这种情况发生在两个或多个Bean在其构造函数中相互依赖对方。例如,BeanA的构造函数需要一个BeanB的实例,而BeanB的构造函数又需要一个BeanA的实例。
    • 结果 :Spring无法解决构造器循环依赖,因为这会导致死锁。当Spring尝试创建BeanA时,它会因为缺少BeanB而阻塞;同样,当Spring尝试创建BeanB时,它会因为缺少BeanA而阻塞。
  • Setter方法注入循环依赖:
    • 这种情况发生在两个或多个Bean在其setter方法或通过其他方法注入中相互依赖对方。例如,BeanA有一个setter方法需要一个BeanB的实例,而BeanB有一个setter方法需要一个BeanA的实例。
    • 结果:Spring可以解决Setter/方法注入循环依赖,因为它允许在Bean的属性被填充后再进行其他Bean的属性注入。

4. 解决方案

4.1 解决Setter方法注入循环依赖
  1. 三级缓存机制

    • 一级缓存(singletonObjects):存储已经完全初始化好的Bean实例。

    • 二级缓存(earlySingletonObjects):存储Bean的早期引用,这些Bean实例已经实例化但还未完成属性注入和初始化。

    • 三级缓存(singletonFactories):存储Bean工厂对象,用于创建二级缓存中的Bean实例。

  2. 解决过程

    • 当Spring容器开始创建一个Bean时,它会首先检查三级缓存中是否已经有这个Bean的工厂对象。如果有,说明这个Bean正在创建中,Spring容器会从三级缓存中获取工厂对象,创建Bean的早期引用,并将其放入二级缓存中。

    • 然后,Spring容器会继续处理这个Bean的属性注入。如果属性依赖其他Bean,Spring容器会尝试从二级缓存中获取这些Bean的早期引用,而不是等待它们完全初始化。

    • 当所有属性注入完成后,Spring容器会将Bean从二级缓存移动到一级缓存,并执行Bean的初始化方法。

    • 如果在属性注入过程中发现循环依赖,Spring容器可以利用二级缓存中的早期引用来解决这个问题,因为这些早期引用已经包含了部分初始化的数据

4.2 解决构造器循环依赖

对于构造器循环依赖,Spring没有内置的解决方案。解决这类问题的常见方法包括:

  • 重新设计组件:重新设计组件之间的依赖关系,避免构造器循环依赖。
  • 使用Setter注入:将构造器注入改为Setter注入,利用Spring的循环依赖解决方案。
  • 使用原型Bean:将其中一个Bean的scope设置为prototype,因为原型Bean在每次请求时都会创建新的实例,从而避免循环依赖。
相关推荐
paopaokaka_luck7 分钟前
绿色环保活动平台(AI问答、WebSocket即时通讯、协同过滤算法、Echarts图形化分析)
java·网络·vue.js·spring boot·websocket·网络协议·架构
齐穗穗7 分钟前
springboot集成websocket
spring boot·后端·websocket
在路上`18 分钟前
前端学习之后端java小白(二)-sql约束/建表
java·sql·学习
真*小白31 分钟前
Python语法学习篇(三)【py3】
开发语言·python·学习
lingggggaaaa38 分钟前
小迪安全v2023学习笔记(八十二讲)—— Java组件安全&Solr&Shiro&Log4j&CVE复现
笔记·学习·安全
好望角雾眠42 分钟前
第四阶段C#通讯开发-1:通讯基础理论,串口,通讯模式,单位转换,代码示例
开发语言·笔记·c#·串口·通讯
不一样的故事1261 小时前
学习Python是一个循序渐进的过程,结合系统学习、持续实践和项目驱动,
开发语言·python·学习
菜菜子爱学习1 小时前
系统架构设计师——【2025年上半年案例题】真题分享(一)
学习·系统架构·软考·系统架构设计师
一只乔哇噻1 小时前
java后端工程师进修ing(研一版‖day44)
java·开发语言·学习·算法
老华带你飞1 小时前
畅阅读小程序|畅阅读系统|基于java的畅阅读系统小程序设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·小程序·毕设·畅阅读系统小程序