spring循环依赖以及MyBatis-Plus的继承特性导致循环依赖自动解决失效

server/2024/11/25 13:40:43/

在 Spring 中,循环依赖是指两个或多个 bean 之间相互依赖,形成一个循环引用的情况。Spring 对于循环依赖有一定的处理机制,但也存在一些限制。

一、Spring 处理循环依赖的方式

  1. 三级缓存解决构造函数注入的循环依赖

    • Spring 首先创建一个正在创建中的 bean 对象,并将其放入一个 “正在创建的 bean 缓存”(一级缓存)中。
    • 当遇到循环依赖时,Spring 会尝试从 “正在创建的 bean 缓存” 中获取 bean 对象,如果获取到,则说明循环依赖已经被解决。
    • 如果在 “正在创建的 bean 缓存” 中没有找到 bean 对象,Spring 会从 “早期单例对象缓存”(二级缓存)中获取 bean 对象。如果获取到,则说明该 bean 对象已经被创建,并且是一个单例对象,可以直接返回。
    • 如果在 “早期单例对象缓存” 中也没有找到 bean 对象,Spring 会从 “单例对象缓存”(三级缓存)中获取 bean 对象。如果获取到,则说明该 bean 对象已经被创建,并且是一个单例对象,可以直接返回。
  2. setter 注入的循环依赖处理

    • Spring 在处理 setter 注入的循环依赖时,会先创建 bean 对象,然后再设置其依赖的属性。
    • 当遇到循环依赖时,Spring 会先创建一个 bean 对象,并将其放入 “正在创建的 bean 缓存” 中。然后,Spring 会尝试从 “正在创建的 bean 缓存” 中获取依赖的 bean 对象。如果获取到,则说明循环依赖已经被解决。如果没有获取到,则继续创建依赖的 bean 对象,并将其放入 “正在创建的 bean 缓存” 中。

二、Spring 处理循环依赖的限制

  1. 构造函数注入的限制

    • 如果循环依赖中的 bean 对象是通过构造函数注入的,并且构造函数中存在循环依赖的参数,那么 Spring 无法解决这种循环依赖。
    • 例如,如果有两个 bean 对象 A 和 B,A 的构造函数中依赖 B,B 的构造函数中依赖 A,那么 Spring 无法创建这两个 bean 对象。
  2. 原型 bean 的限制

    • Spring 对于原型(prototype)bean 的循环依赖无法处理。
    • 原型 bean 每次请求都会创建一个新的实例,因此无法在创建过程中解决循环依赖。

三、解决循环依赖的方法

  1. 重构代码

    • 检查代码中的循环依赖关系,尝试通过重构代码来消除循环依赖。
    • 可以将循环依赖的部分提取到一个单独的 bean 中,或者使用依赖注入的替代方法,如 setter 注入或方法注入。
  2. 使用 @Lazy 注解

    • 在循环依赖的 bean 中,可以使用@Lazy注解来延迟加载依赖的 bean。
    • 这样,当 Spring 创建 bean 对象时,不会立即创建依赖的 bean 对象,而是在需要时才创建。
    • 这种方法可以在一定程度上解决循环依赖问题,但需要注意的是,使用@Lazy注解可能会影响性能,因为依赖的 bean 对象只有在需要时才会被创建。
  3. 使用 @DependsOn 注解

    • @DependsOn注解可以指定一个 bean 的初始化顺序。
    • 在循环依赖的情况下,可以使用@DependsOn注解来确保一个 bean 在另一个 bean 之前被初始化。
    • 例如,如果有两个 bean 对象 A 和 B,A 的初始化依赖于 B,那么可以在 A 的类上使用@DependsOn("B")注解,确保 B 在 A 之前被初始化。

总之,Spring 对于循环依赖有一定的处理机制,但也存在一些限制。在实际应用中,应该尽量避免循环依赖的情况发生,如果无法避免,可以通过重构代码、使用@Lazy注解或@DependsOn注解等方法来解决循环依赖问题。

四、MyBatis-Plus的继承特性导致循环依赖(Spring的三级缓存机制无法正常工作)

在使用MyBatis-Plus时,服务实现类(如PXXServiceImpl)通常会继承ServiceImpl类,并实现对应的服务接口(如IPXXService)。这种继承关系可能会导致Spring在创建Bean时遇到循环依赖的问题


Spring的三级缓存机制:Spring的三级缓存机制主要解决的是字段注入(Field Injection)或setter方法注入(Setter Injection)引起的循环依赖问题。对于构造函数注入(Constructor Injection),Spring无法解决循环依赖,因为构造函数注入要求所有依赖在Bean创建时必须是可用的


MyBatis-Plus的Bean包装:有观点认为,由于Service集成了MyBatis-Plus的基类,Spring可能将其视为“包装过的类”,这可能导致Spring的三级缓存机制无法正常工作,从而引发循环依赖问题。

解决方案
使用@Lazy注解:在Spring中,可以通过在注入的字段上添加@Lazy注解来延迟Bean的加载,这样可以避免循环依赖的问题。

抽象中间Service:可以通过创建一个中间Service层来避免直接的循环依赖,这样可以减少直接的依赖关系,从而避免循环依赖。

使用Setter方法注入:而不是字段注入或构造函数注入,Setter方法注入可以更好地与Spring的三级缓存机制配合,解决循环依赖问题。

重新设计架构:如果可能,重新设计服务层的架构,减少服务之间的直接依赖,或者将一些共用的服务抽象出来,以减少循环依赖的可能性。

综上所述,MyBatis-Plus的继承特性和Spring的Bean包装可能导致Spring的三级缓存机制无法完全解决循环依赖问题。您可以尝试上述解决方案来避免或解决循环依赖问题。


http://www.ppmy.cn/server/144808.html

相关文章

C++结构型设计模式之使用抽象工厂来创建和配置桥接模式的例子

下面是一个使用抽象工厂模式来创建和配置桥接模式的示例&#xff0c;场景是创建不同操作系统的窗口&#xff08;Window&#xff09;及其对应的实现&#xff08;WindowImpl&#xff09;。我们将通过抽象工厂来创建不同操作系统下的窗口和实现。 代码示例 #include <iostrea…

机器学习周志华学习笔记-第5章<神经网络>

机器学习周志华学习笔记-第5章<神经网络> 卷王&#xff0c;请看目录 5模型的评估与选择5.1 神经元模型5.2 感知机与多层网络5.3 BP(误逆差)神经网络算法 5.4常见的神经网络5.4.1 RBF网络&#xff08;Radial Basis Function Network&#xff0c;径向基函数网络&#xff0…

移动光猫[HS8545M5-10]获取超密

移动光猫[HS8545M5-10]获取超级密码 1、缘由2、前期准备2.1、确保本地开通telnet客户端功能2.2、准备好相关软件 3、开始查找超密 1、缘由 最近想折腾一下ipv6ddns打通内外网&#xff0c;查询资料说是需要将光猫桥接到外网&#xff1b;但是使用光猫后边的用户名密码根本就找不到…

kafka是如何做到高效读写

消息持久化&#xff1a; Kafka 将消息存储在磁盘上&#xff0c;并且通过顺序写入的方式提高写入性能。 消息被追加到日志文件的尾部&#xff0c;避免了随机写操作&#xff0c;从而提高了写入速度。零拷贝技术&#xff1a;利用操作系统的零拷贝特性&#xff0c;数据可以从磁盘直…

Spring Boot OA:构建企业级办公自动化平台

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了企业OA管理系统的开发全过程。通过分析企业OA管理系统管理的不足&#xff0c;创建了一个计算机管理企业OA管理系统的方案。文章介绍了企业OA管理系统的系统分析部…

使用LUKS对Linux磁盘进行加密

前言 本实验用于日常学习用&#xff0c;如需对存有重要数据的磁盘进行操作&#xff0c;请做好数据备份工作。 此实验只是使用LUKS工具的冰山一角&#xff0c;后续还会有更多功能等待探索。 LUKS&#xff08;Linux Unified Key Setup&#xff09;是Linux系统中用于磁盘加密的一…

【计算机网络】数据链路层

跨网络传输的本质&#xff1a;由许多局域网(子网)转发的结果 要彻底理解跨网络转发&#xff0c;首先要理解 -> 局域网中报文的转发原理&#xff01; ​​​​​​​ 一、以太网帧格式 1.报头的含义 源地址/目的地址&#xff1a;源MAC地址和目的MAC地址 帧协议类型&…

大语言模型---LoRA中损失值的计算

文章目录 概要损失计算流程小结 概要 Llama-7B模型的LoRA微调训练中&#xff0c;通过使用Cross-Entropy Loss来度量模型输出的预测分布和真实标签分布之间的距离&#xff0c;来衡量模型的准确性。 本文主要介绍LoRA中损失值的计算流程。 Cross-Entropy Loss作用&#xff1a;是…