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在每次请求时都会创建新的实例,从而避免循环依赖。
相关推荐
星辰徐哥21 分钟前
Spring Boot 微服务架构设计与实现
spring boot·后端·微服务
星辰徐哥22 分钟前
Spring Boot 数据导入导出与报表生成
spring boot·后端·ui
明夜之约23 分钟前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee23 分钟前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Micro麦可乐24 分钟前
Spring Boot 实战:从零设计一个短链系统(含完整代码与数据库设计)
数据库·spring boot·后端·哈希算法·雪花算法·短链系统
Jinkxs26 分钟前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
毕设源码_郑学姐27 分钟前
计算机毕业设计springboot网络相册设计与实现 基于Spring Boot框架的在线相册管理系统开发与应用 Spring Boot驱动的网络影集设计与实践
spring boot·后端·课程设计
辣机小司27 分钟前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录
一条小锦吕*30 分钟前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
Jinkxs30 分钟前
Prometheus - 监控微服务:Spring Boot 应用指标暴露与监控
spring boot·微服务·prometheus