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在每次请求时都会创建新的实例,从而避免循环依赖。
相关推荐
守护者17014 分钟前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
学会沉淀。23 分钟前
Docker学习
java·开发语言·学习
Rinai_R38 分钟前
计算机组成原理的学习笔记(7)-- 存储器·其二 容量扩展/多模块存储系统/外存/Cache/虚拟存储器
笔记·物联网·学习
吃着火锅x唱着歌38 分钟前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
ragnwang41 分钟前
C++ Eigen常见的高级用法 [学习笔记]
c++·笔记·学习
初晴~1 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
胡西风_foxww1 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
黑胡子大叔的小屋2 小时前
基于springboot的海洋知识服务平台的设计与实现
java·spring boot·毕业设计
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript