当前位置: 首页 > news >正文

Spring Boot解决循环注入问题

Spring Boot解决循环依赖注入问题

  • 代码问题回显
  • 启动错误日志
  • 解决方案:使用事件驱动或通过 ApplicationContext 手动获取 Bean
    • 1. 事件驱动设计
    • 2. 使用 `ApplicationContext` 手动获取 Bean
    • 3. 拆分逻辑
  • 总结

代码问题回显

现有代码1 在InterestService中依赖MemberInterestService

@Service
@AllArgsConstructor
public class InterestService {// 注意此处循环依赖注入private final MemberInterestService memberInterestService;private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);/*** 调度下一个利息任务*/public void scheduleNextInterestTask() {// 省略其他代码...}
}

现有代码2 在MemberInterestService实现类中注入InterestService

@Service
@AllArgsConstructor
public class MemberInterestServiceImpl extends ServiceImpl<MemberInterestMapper, MemberInterest> implements MemberInterestService {// 注意此处循环依赖注入private final InterestService interestService;@Overridepublic Boolean updateExpireStatus(MemberInterestExpireStatus body) {// 省略其他代码...if (updateById(interest)){// TODO 此处出现循环依赖注入(直接报错)interestService.scheduleNextInterestTask();return true;}}
}

启动错误日志

Description:
The dependencies of some of the beans in the application context form a cycle:   
mobileLoginController (field private com.sinbyte.framework.web.service.SysLoginService 
com.sinbyte.web.controller.system.MobileLoginController.loginService)      
↓   
sysLoginService (field private com.sinbyte.ray.service.MemberUserService 
com.sinbyte.framework.web.service.SysLoginService.memberUserService)
┌─────┐
|  memberInterestServiceImpl defined in file [D:\Java\IdeaProjects\alliance-server\alliance-ray\target\classes\com\sinbyte\ray\service\impl\MemberInterestServiceImpl.class]
↑     ↓
|  interestService defined in file [D:\Java\IdeaProjects\alliance-server\alliance-ray\target\classes\com\sinbyte\ray\delay\InterestService.class]
└─────┘

在场景中, MemberInterestServiceImpl 需要调用 InterestServicescheduleNextInterestTask() 方法,但由于这两个服务之间存在循环依赖,直接注入会导致 Spring 启动时发生循环依赖错误

解决方案:使用事件驱动或通过 ApplicationContext 手动获取 Bean

以下是一些可以解决循环依赖问题的方法:

1. 事件驱动设计

可以使用 Spring 的事件机制,将调用 scheduleNextInterestTask 的操作转变为事件驱动。具体做法是,当 MemberInterestServiceImpl 需要调用 scheduleNextInterestTask 时,发布一个自定义事件,InterestService 监听这个事件并执行相应的任务。

首先,定义一个自定义事件类:

import org.springframework.context.ApplicationEvent;
/*** 自定义事件驱动* @CreateDate: 2024/8/14 15:30*/
public class InterestTaskEvent extends ApplicationEvent {public InterestTaskEvent(Object source) {super(source);}
}

接着,在 MemberInterestServiceImpl 中发布事件,实现ApplicationEventPublisherAware并重写setApplicationEventPublisher方法:

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;@Service
@AllArgsConstructor
public class MemberInterestServiceImpl extends ServiceImpl<MemberInterestMapper, MemberInterest> implements MemberInterestService, ApplicationEventPublisherAware {// 事件发布器private ApplicationEventPublisher eventPublisher;@Overridepublic void setApplicationEventPublisher(@NotNull ApplicationEventPublisher applicationEventPublisher) {// 注入事件发布器this.eventPublisher = applicationEventPublisher;}@Overridepublic Boolean updateExpireStatus(MemberInterestExpireStatus body) {// 省略其他代码...if (updateById(interest)) {// 省略其他代码...eventPublisher.publishEvent(new InterestTaskEvent(this));  // 发布事件return true;}}
}

InterestService 中监听这个事件:

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;@Service
@AllArgsConstructor
public class InterestService {// 其他依赖...@EventListenerpublic void onInterestTaskEvent(InterestTaskEvent event) {scheduleNextInterestTask();}public void scheduleNextInterestTask() {// 省略其他代码...}
}

2. 使用 ApplicationContext 手动获取 Bean

如果你不希望使用事件驱动,还可以通过 Spring 的 ApplicationContext 手动获取 InterestService Bean,从而避免循环依赖。

MemberInterestServiceImpl 中引入 ApplicationContext 并在需要调用时获取 InterestService

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;@Service
@Slf4j
@AllArgsConstructor
public class MemberInterestServiceImpl extends ServiceImpl<MemberInterestMapper, MemberInterest> implements MemberInterestService, ApplicationContextAware {private ApplicationContext applicationContext;private final RedisCache redisCache;private final PublicService publicService;private final MemberApplyBusinessService memberApplyBusinessService;private final MemberTransactionRecordService memberTransactionRecordService;private final MemberInterestPointService memberInterestPointService;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic Boolean updateExpireStatus(MemberInterestExpireStatus body) {// 省略其他代码...if (updateById(interest)) {// 省略其他代码...InterestService interestService = applicationContext.getBean(InterestService.class);interestService.scheduleNextInterestTask();  // 手动获取 Bean 并调用方法return true;}throw new ServiceException("更新失败");}
}

3. 拆分逻辑

如果可能,考虑将 InterestService 的部分逻辑拆分到一个新的服务中,以减少 InterestServiceMemberInterestServiceImpl 之间的依赖关系。这可能需要对业务逻辑进行一定的重构,但从长期维护的角度来看,是一种更优雅的解决方案。

总结

通过以上方法,可以有效地解决循环依赖问题并在 MemberInterestServiceImpl 中安全地调用 InterestService 的方法。推荐使用事件驱动的方法,这不仅解决了循环依赖问题,还能让你的代码更具扩展性和松耦合。

生活不能过度的平坦,这样的生活才最有意义!

相关文章:

Spring Boot解决循环注入问题

Spring Boot解决循环依赖注入问题 代码问题回显启动错误日志解决方案&#xff1a;使用事件驱动或通过 ApplicationContext 手动获取 Bean1. 事件驱动设计2. 使用 ApplicationContext 手动获取 Bean3. 拆分逻辑 总结 代码问题回显 现有代码1 在InterestService中依赖MemberInte…...

《数据挖掘》期末考核重点

1.数据预处理的目的与形式 数据预处理的目的是提供干净&#xff0c;简洁&#xff0c;准确的数据&#xff0c;以达到简化模型和提高算法泛化能力的目的&#xff0c;使挖掘过程更有效&#xff0c;更容易&#xff0c;提高挖掘效率和准确性。 2.数据预处理的形式 数据清理&#…...

Golang | Leetcode Golang题解之第334题递增的三元子序列

题目&#xff1a; 题解&#xff1a; func increasingTriplet(nums []int) bool {n : len(nums)if n < 3 {return false}first, second : nums[0], math.MaxInt32for i : 1; i < n; i {num : nums[i]if num > second {return true} else if num > first {second n…...

HarmonyOs编写一个案例实现一个照片选择(阶段进阶 四种需求 逐一完善)

需求1. .实现照片选择 并将选择好的照片展示出来 import { GoodItem } from ../06/modules;Entry Component struct PhotoPage {State message: string 实现一个相册;State List: GoodItem[] [{goods_name: dsfjlsjkfsf,goods_price: 100,goods_img: https://img1.baidu.com…...

洗衣机洗衣服一些知识

01智能:按衣物多少自动调节合适水位的标准洗涤程序 (需要30分钟时间) 02:大物:较大,较厚的衣服洗涤 03:轻柔:毛织品或内衣洗涤 04:快速:少量清污衣服洗涤 (13分钟) 05:浸泡:先浸泡一段时间再洗涤 06:单洗:只洗衣不脱水 07:单脱:只脱水不洗衣 08:洁桶:清洁洗衣桶 准备工作: (1)…...

探索文件系统:高效、可靠的文件管理与访问机制

文件系统的功能规划 内存就像是一个书包&#xff0c;容量有限&#xff0c;只能带着一部分东西。而图书馆则是一个专门存储和管理文件的地方&#xff0c;拥有更大的容量&#xff0c;并且可以永久保存文件。为了能够快速找到需要的文件&#xff0c;我们需要有一个书单来记录每本…...

启程与远征Ⅸ--优化生成式人工智能以满足业务需求的框架

生成类似人类的文本和语音曾经只存在于科幻小说中。但 GPT-3 和 PaLM 等大型语言模型 (LLM) 的快速发展让这一愿景更接近现实&#xff0c;解锁了从聊天机器人到内容创作等一系列有前景的商业应用。 然而&#xff0c;通用基础模型往往无法满足行业用例的需求。企业对其生成式 A…...

canal数据同步工具介绍与应用

canal服务 canal介绍canal版本与环境canal 服务集canal应用场景&#xff1a; canal常见问题xml配置问题连接认证问题jar版本问题连接问题 canal介绍 ‌1、Canal是‌阿里巴巴开源的‌MySQL增量数据订阅和消费工具&#xff0c;通过模拟MySQL的‌slave与‌master交互&#xff0c;捕…...

ubuntu18.04 设置静态地址

修改配置文件 sudo vim /etc/netplan/01-network-manager-all.yaml 代码如下&#xff1a; network: version: 2 renderer: NetworkManager ethernets: ens33: # 配置的网卡名称&#xff0c;可以使用ifconfig -a查看本机的网卡 dhcp4: no # 关闭动态IP设置 …...

jira敏捷开发管理工具视频教程Confluence工作流协同开发(2024)

正文&#xff1a; 随着Jira敏捷开发方法论的普及&#xff0c;Jira已经成为全球软件开发团队管理项目、任务和问题的首选工具。为了帮助团队更好地掌握Jira的核心功能&#xff0c;精心准备了一套全面开发技术及案例视频教程——《Jira敏捷开发管理工具视频教程Confluenc…...

【网络】TCP回显服务器和客户端的构造,以及相关bug解决方法

文章目录 ServerSocket构造方法方法 Socket构造方法方法 回显服务器&#xff08;Echo Server&#xff09;1. 构造方法2. 建立连接processConnection 方法的创建1. 读取请求并解析2. 根据请求计算响应3. 把响应写回给客户端 3. 完整代码 客户端&#xff08;Echo Client&#xff…...

Python知识点:如何使用Boto3进行AWS服务管理

使用 boto3 来管理 AWS 服务是一个非常强大的方式&#xff0c;因为 boto3 是 AWS 提供的官方 Python SDK。下面是使用 boto3 管理 AWS 服务的基本步骤&#xff0c;包括设置、操作和常见的 AWS 服务示例。 1. 安装 boto3 首先&#xff0c;确保你已经安装了 boto3。可以使用 pi…...

Java - 正则表达式

Java 提供了 java.util.regex 包&#xff0c;它包含了 Pattern 和 Matcher 类&#xff0c;用于处理正则表达式的匹配操作。 正则表达式的模式 正则表达式的模式可以包括以下内容&#xff1a; 字面值字符&#xff1a;例如字母、数字、空格等&#xff0c;可以直接匹配它们自身。…...

Vue一款流行的JavaScript前端框架

1.Vue简介 Vue是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。无论是简单还是复杂的界面&#xff0c;Vue 都可以胜任。 Vue所关注的核心是MVC…...

GPT-SoVITS

文章目录 model archS1 ModelS2 model model arch S1 model: AR model–ssl tokensS2 model: VITS&#xff0c;ssl 已经是mel 长度线性相关&#xff0c;MRTE(ssl_codes_embs, text, global_mel_emb)模块&#xff0c;将文本加强相关&#xff0c;学到一个参考结果 S1 Model cla…...

linux高级编程——文件IO(常用函数大全)

1.相关介绍及常用函数 Linux高级编程中的目录IO操作是文件系统编程的一个重要组成部分&#xff0c;主要涉及到目录的打开、读取、遍历和关闭等操作。以下是一些基本的目录IO操作和相关的系统调用函数 1.1 opendir函数 打开目录&#xff1a;使用opendir函数打开一个目录&#…...

matplotlib画图

Matplotlib 先写一个最简单的&#xff1a; import matplotlib.pyplot as plt plt.plot([1,4],[2,8]) #plot画折线图plt.show() 确定两个点画一条线 import matplotlib.pyplot as plt x[1,23,4,56,7,6] #x轴数据 y[22,44,56,67,43,2] #y轴数据 s[22,43,33,44,43,7] plt.p…...

Jetpack 各种框架简介

Jetpack是Google推出的一套为Android开发提供极大便利的组件、工具和指导集&#xff0c;旨在帮助开发者快速构建高质量的应用&#xff0c;并遵循最佳实践。 Jetpack不仅是一个提高开发效率的工具集&#xff0c;还是Android开发的未来方向。它通过整合各种组件和工具&#xff0…...

海康VisionMaster使用学习笔记5-开机自启动

开机自启动 在实际应用中&#xff0c;用户会希望机台上电开机后&#xff0c;软件能自启动避免现场人员误操作&#xff0c;减少机台重新上电时的操作步骤以提升效率。 设置 打开VM,点击设置,软件设置->开机自启动->勾选开机自启动->确定 默认运行界面 启动时以设定的…...

驾驭数据之序:SQL序列的奥秘与实现

标题&#xff1a;驾驭数据之序&#xff1a;SQL序列的奥秘与实现 摘要 在数据库管理中&#xff0c;保证数据的有序性和唯一性是至关重要的。SQL序列&#xff08;Sequence&#xff09;作为一种强大的数据库对象&#xff0c;为我们提供了一种在不同数据库系统中生成连续数字的手…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

【Ftrace 专栏】Ftrace 参考博文

ftrace、perf、bcc、bpftrace、ply、simple_perf的使用Ftrace 基本用法Linux 利用 ftrace 分析内核调用如何利用ftrace精确跟踪特定进程调度信息使用 ftrace 进行追踪延迟Linux-培训笔记-ftracehttps://www.kernel.org/doc/html/v4.18/trace/events.htmlhttps://blog.csdn.net/…...

用 FFmpeg 实现 RTMP 推流直播

RTMP&#xff08;Real-Time Messaging Protocol&#xff09; 是直播行业中常用的传输协议。 一般来说&#xff0c;直播服务商会给你&#xff1a; ✅ 一个 RTMP 推流地址&#xff08;你推视频上去&#xff09; ✅ 一个 HLS 或 FLV 拉流地址&#xff08;观众观看用&#xff09;…...