Spring Events在大型项目中的最佳实践

在大型项目中,Spring Events提供了一种有效的方式来解耦不同的模块,使得系统更加灵活和可扩展。Spring Events基于发布/订阅模式,允许应用的不同部分之间进行通信,而无需直接调用对方的代码。这种方式特别适合于处理那些不需要即时反馈的业务场景。

实际业务场景

假设我们正在开发一个电子商务平台,其中涉及到订单处理、库存管理、用户通知等多个模块。当一个订单被创建时,我们需要执行以下操作:

  1. 更新库存信息。
  2. 发送订单创建通知给用户。
  3. 记录订单日志。

这些操作可以独立执行,且不需要即时反馈。因此,我们可以使用Spring Events来处理这些操作。

代码示例

首先,我们定义一个订单创建事件:

java
import org.springframework.context.ApplicationEvent;public class OrderCreatedEvent extends ApplicationEvent {private final String orderId;public OrderCreatedEvent(Object source, String orderId) {super(source);this.orderId = orderId;}public String getOrderId() {return orderId;}
}

接下来,我们创建一个发布这个事件的Publisher:

java
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;@Component
public class OrderCreatedPublisher {private final ApplicationEventPublisher publisher;public OrderCreatedPublisher(ApplicationEventPublisher publisher) {this.publisher = publisher;}public void publishOrderCreatedEvent(String orderId) {OrderCreatedEvent event = new OrderCreatedEvent(this, orderId);publisher.publishEvent(event);}
}

然后,我们定义几个监听器来处理这个事件:

java
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@Component
public class InventoryUpdateListener {@EventListenerpublic void onOrderCreated(OrderCreatedEvent event) {String orderId = event.getOrderId();// 更新库存逻辑System.out.println("Inventory updated for order: " + orderId);}
}@Component
public class UserNotificationListener {@EventListenerpublic void onOrderCreated(OrderCreatedEvent event) {String orderId = event.getOrderId();// 发送通知给用户System.out.println("User notified for order: " + orderId);}
}@Component
public class OrderLoggingListener {@EventListenerpublic void onOrderCreated(OrderCreatedEvent event) {String orderId = event.getOrderId();// 记录订单日志System.out.println("Order logged: " + orderId);}
}

最佳实践

  1. 异步处理:默认情况下,Spring Events是同步处理的,这意味着事件发布者需要等待所有监听器处理完事件后才能继续执行。在大型项目中,这可能会导致性能问题。因此,建议使用@Async注解来异步处理事件。
  2. 避免依赖监听器执行顺序:虽然可以使用@Order注解来指定监听器的执行顺序,但在异步执行的情况下,这种顺序是不可控的。因此,应避免在监听器之间创建依赖关系。
  3. 错误处理:事件发布者无法获知哪些订阅消费失败,哪些订阅者成功。因此,需要在监听器中妥善处理可能发生的异常,确保系统的稳定性。
  4. 最终一致性:对于那些不需要强一致性的业务场景,如日志记录、发送通知等,使用Spring Events是非常合适的。
  5. 事件的可靠性:由于Spring Events在单个应用内部的事件通知机制,如果应用崩溃或者重启,事件将会丢失。因此,对于关键业务,可能需要考虑使用消息队列等更可靠的机制。

通过以上实践,Spring Events可以在大型项目中发挥重要作用,帮助开发者构建一个更加模块化和可维护的系统

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/473793.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nature Communications 基于触觉手套的深度学习驱动视触觉动态重建方案

在人形机器人操作领域,有一个极具价值的问题:鉴于操作数据在人形操作技能学习中的重要性,如何有效地从现实世界中获取操作数据的完整状态?如果可以,那考虑到人类庞大规模的人口和进行复杂操作的简单直观性与可扩展性&a…

ReactPress与WordPress:一场内容管理系统的较量

ReactPress Github项目地址:https://github.com/fecommunity/reactpress WordPress官网:https://wordpress.org/ ReactPress与WordPress:一场内容管理系统的较量 在当今数字化时代,内容管理系统(CMS)已成为…

解决Windows远程桌面 “为安全考虑,已锁定该用户账户,原因是登录尝试或密码更改尝试过多。请稍后片刻再重试,或与系统管理员或技术支持联系“问题

当我们远程连接服务器连接不上并提示“为安全考虑,已锁定该用户账户,原因是登录尝试或密码更改尝试过多。请稍候片刻再重试,或与系统管理员或技术支持联系”时,根本原因是当前计算机远程连接时输入了过多的错误密码,触…

Cyberchef配合Wireshark提取并解析TCP/FTP流量数据包中的文件

前一篇文章中讲述了如何使用cyberchef提取HTTP/TLS数据包中的文件,详见《Cyberchef配合Wireshark提取并解析HTTP/TLS流量数据包中的文件》,链接这里,本文讲述下如何使用cyberchef提取FTP/TCP数据包中的文件。 FTP 是最为常见的文件传输协议,和HTTP协议不同的是FTP协议传输…

vs2022搭建opencv开发环境

1 下载OpenCV库 https://opencv.org/ 下载对应版本然后进行安装 将bin目录添加到系统环境变量opencv\build\x64\vc16\bin 复制该路径 打开高级设置添加环境变量 vs2022新建一个空项目 修改属性添加头文件路径和库路径 修改链接器,将OpenCV中lib库里的o…

构建SSH僵尸网络

import argparse import paramiko# 定义一个名为Client的类,用于表示SSH客户端相关操作 class Client:# 类的初始化方法,接收主机地址、用户名和密码作为参数def __init__(self, host, user, password):self.host hostself.user userself.password pa…

【开源免费】基于SpringBoot+Vue.JS购物推荐网站(JAVA毕业设计)

博主说明:本文项目编号 T 073 ,文末自助获取源码 \color{red}{T073,文末自助获取源码} T073,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

PG-DERN 解读:少样本学习、 双视角编码器、 关系图学习网络

本文提出了一种用于 分子属性预测 的 少样本学习(Few-shot Learning) 模型—— PG-DERN,该模型结合了 双视角编码器(Dual-view Encoder) 和 关系图学习网络(Relation Graph Learning Network) 双…

RabbitMQ-死信队列(golang)

1、概念 死信(Dead Letter),字面上可以理解为未被消费者成功消费的信息,正常来说,生产者将消息放入到队列中,消费者从队列获取消息,并进行处理,但是由于某种原因,队列中的…

Uni-APP+Vue3+鸿蒙 开发菜鸟流程

参考文档 文档中心 运行和发行 | uni-app官网 AppGallery Connect DCloud开发者中心 环境要求 Vue3jdk 17 Java Downloads | Oracle 中国 【鸿蒙开发工具内置jdk17,本地不使用17会报jdk版本不一致问题】 开发工具 HBuilderDevEco Studio【目前只下载这一个就…

Python中的with语句

with语句和上下文管理器 Python提供了 with 语句的写法,既简单又安全 文件操作的时候使用with语句可以自动调用关闭文件操作,即使出现异常也会自动关闭文件操作。 # 1、以写的方式打开文件 with open(1.txt, w) as f:# 2、读取文件内容f.write(hello wor…

SQL面试题——抖音SQL面试题 主播播出时长

主播播出时长 现有如下数据,主播id、房间号、播出的批次号,每个批次号进出房间的时间戳、分区时间: 每一次直播都有一个上播和下播,每个房间里,同一个批次号会有两条数据,分别记录了上播和下播时间,求每个主播的播出时长? 通过上面的数据,可以清晰的看出,同一个批次…

【汇编】c++游戏开发

由一起学编程创作的‘C/C项目实战:2D射击游戏开发(简易版), 440 行源码分享来啦~’: C/C项目实战:2D射击游戏开发(简易版), 440 行源码分享来啦~_射击c-CSDN博客文章浏览…

Uniapp 引入 Android aar 包 和 Android 离线打包

需求: 原生安卓 apk 要求嵌入到 uniapp 中,并通过 uniapp 前端调起 app 的相关组件。 下面手把手教你,从 apk 到 aar,以及打包冲突到如何运行,期间我所遇到的问题都会 一 一 进行说明,相关版本以我文章内为…

自动化运维(k8s):一键获取指定命名空间镜像包脚本

前言:脚本写成并非一蹴而就,需要不断的调式和修改,这里也是改到了7版本才在 生产环境 中验证成功。 该命令 和 脚本适用于以下场景:在某些项目中,由于特定的安全或政策要求,不允许连接到你的镜像仓库。然而…

Vue2+ElementUI:用计算属性实现搜索框功能

前言: 本文代码使用vue2element UI。 输入框搜索的功能,可以在前端通过计算属性过滤实现,也可以调用后端写好的接口。本文介绍的是通过计算属性对表格数据实时过滤,后附完整代码,代码中提供的是死数据,可…

机器学习(1)

一、机器学习 机器学习(Machine Learning, ML)是人工智能(Artificial Intelligence, AI)的一个分支,它致力于开发能够从数据中学习并改进性能的算法和模型。机器学习的核心思想是通过数据和经验自动优化算法&#xff…

【Linux学习】【Ubuntu入门】1-4 ubuntu终端操作与shell命令1

1.使用快捷键CtrlAltT打开命令终端,或者单击右键点击… 2.常用shell命令 目录信息查看命令:ls ls -a:显示目录所有文件及文件夹,包括隐藏文件,比如以.开头的 ls -l:显示文件的详细信息 ls -al&#xff1…

Oracle OCP认证考试考点详解082系列19

题记: 本系列主要讲解Oracle OCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。 91. 第91题: 题目 解析及答案: 关于 Oracle 数据库中的索引及其管理,以下哪三个陈述是正确的&#x…

智能网页内容截图工具:AI助力内容提取与可视化

我们每天都会接触到大量的网页内容。然而,如何从这些内容中快速提取关键信息,并有效地进行整理和分享,一直是困扰我们的问题。本文将介绍一款我近期完成的基于AI技术的智能网页内容截图工具,它能够自动分析网页内容,截…