Spring 事件驱动编程初探:用 @EventListener 轻松处理业务通知

一、核心概念与模型

Spring 的事件机制是观察者模式(也叫发布-订阅模型)的一种典型实现。它主要由三个核心部分组成:

  1. 事件 (Event): 承载信息的对象,通常是某种状态变化的通知。可以是继承 ApplicationEvent 的类,也可以是任何普通的 Java 对象(POJO)。

  2. 发布者 (Publisher): 负责产生并发布事件的组件。它通过 ApplicationEventPublisher 来发布事件。

  3. 监听器 (Listener): 负责接收和处理事件的组件。它监听特定类型的事件并做出响应。

工作流程:发布者发布一个事件 -> Spring 的 ApplicationContext(作为事件广播器)接收事件 -> 广播器将事件通知给所有注册的、对该事件感兴趣的监听器 -> 监听器执行自身的业务逻辑。


二、详细用法与步骤

我们将通过一个经典的业务场景——用户注册成功后,发送邮件和短信——来演示每一步的用法。

第 1 步:定义事件 (Event)

事件是一个简单的 POJO,用于封装需要传递的数据。自 Spring 4.2 以后,不再需要强制继承 ApplicationEvent

package jnpf.model.cultivate.event;import lombok.Getter;
import org.springframework.context.ApplicationEvent;@Getter
public class JnpfApplicationEvent<T> extends ApplicationEvent {private final T data;public JnpfApplicationEvent(T source) {super(source);this.data = source;}
}
第 2 步:发送消息
 SpringContext.getApplicationContext().publishEvent(new JnpfApplicationEvent<>(CourseEventDTO.builder().courseIds(List.of(ftbCultivateCourseDTO.getCourseId())).userIds(new ArrayList<>()).whetherToChange(true).build()));
第 3 步:实现监听器 (Listener)
package jnpf.cultivate.event;import jnpf.model.cultivate.event.JnpfApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;/*** 事件处理程序** @author fantaibao* @date 2023/12/26*/
@Component
public class EventHandler {@Resourceprivate List<JnpfApplicationEventService> jnpfApplicationEventServices;@EventListener(value = JnpfApplicationEvent.class)public <T> void courseEvent(JnpfApplicationEvent<T> jnpfApplicationEvent) {Object data = jnpfApplicationEvent.getData();// 事件处理分发Optional<JnpfApplicationEventService> first = jnpfApplicationEventServices.stream().filter(t -> t.isSupportedCourseEvent(data)).findFirst();first.ifPresent(jnpfApplicationEventService -> jnpfApplicationEventService.handlerCourseEvent(data));}
}
 第 4 步:创建事件处理类接口
package jnpf.cultivate.event;public interface JnpfApplicationEventService {/*** 是否支持此事件** @param event 事件* @return boolean*/boolean isSupportedCourseEvent(Object event);/*** 处理事件** @param courseEvent 事件入参*/void handlerCourseEvent(Object courseEvent);}
第 5 步:事件处理类impl
@Component
@RequiredArgsConstructor
public class JnpfApplicationEventCourseService implements JnpfApplicationEventService {@Overridepublic boolean isSupportedCourseEvent(Object event) {return event instanceof CourseEventDTO;}@Overridepublic void handlerCourseEvent(Object courseEvent) {CourseEventDTO courseEventDTO = (CourseEventDTO) courseEvent;if (CollUtil.isEmpty(courseEventDTO.getCourseIds())) {return;}List<String> userIds = courseEventDTO.getUserIds();//处理逻辑}

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

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

相关文章

无人机也能称重?电力巡检称重传感器安装与使用指南

在无人机电力巡检中&#xff0c;工程师们常常面临一个棘手难题&#xff1a;如何精确知道新架设或老旧缆线的实际负重&#xff1f; 传统依靠老师傅“肉眼估算”的方法不仅风险极高&#xff0c;而且数据极不准确&#xff0c;给电网安全埋下巨大隐患。难道没有更科学的方法吗&…

第二阶段WinForm-8:特性和反射,加密和解密,单例模式

1_预处理指令 &#xff08;1&#xff09;源代码指定了程序的定义&#xff0c;预处理指令&#xff08;preprocessor directive&#xff09;指示编译器如何处理源代码。例如&#xff0c;在某些情况下&#xff0c;我们希望编译器能够忽略一部分代码&#xff0c;而在其他情况下&am…

基于mac的智能语音处理与应用开发-环境部署

上一次写文章还是上一次&#xff0c;时隔一年再次开启学习之路。新机mac没有开发环境&#xff0c;在gpt老师的指导下开始学习之路。 mac开发环境的部署参考了b站程序员云谦和Clover-You的视频教程&#xff0c;然后结合自身及gpt老师的帮助现在开始部署。 g老师的&#x1f34e…

Java中使用正则表达式的正确打开方式

正则表达式基础语法Java正则表达式基于java.util.regex包&#xff0c;核心类是Pattern和Matcher。基本语法遵循标准正则规范&#xff1a;. 匹配任意单个字符&#xff08;除换行符&#xff09;\d 匹配数字&#xff0c;等价于 [0-9]\w 匹配单词字符&#xff0c;等价于 [a-zA-Z0-9…

Docker中Mysql容器忽略大小写

场景说明 在数据迁移场景中&#xff0c;从一个数据库中将数据迁移到另一个数据&#xff0c;经常会遇到&#xff0c;两个不同数据库之间&#xff0c;一个默认忽略大小写&#xff0c;一个默认不忽略大小写&#xff0c;导致实际业务层服务进行数据库访问时&#xff0c;切换数据库之…

神经网络激活函数:从ReLU到前沿SwiGLU

摘要 本文全面介绍了神经网络中常用的激活函数,包括Sigmoid、Tanh、ReLU等传统函数,以及2017年后出现的Swish、Mish、SwiGLU等新兴函数。每个函数均提供数学定义、优缺点分析、Python实现代码和可视化图像,并附有实际应用建议和性能对比数据,帮助读者根据具体任务选择合适…

线程池常见面试问答

好嘞 &#x1f44d;&#xff0c;我帮你把这些 线程池 并发编程八股文 整理成 问答对照表&#xff08;Q & A&#xff09;&#xff0c;你面试时可以直接用。&#x1f9fe; 线程池常见面试问答一、基础语法 & STLQ1&#xff1a;std::function<void()> 和函数指针的…

Flutter 开发技巧 AI 快速构建 json_annotation model 的提示词

将下面这段复制到AI GPT、DeepSeek 、文心快码 试过效果都可以&#xff0c;不用做任何更改。将 json 数据丢给 AI 就行了 我会提供一段 JSON 数据&#xff0c;请帮我生成 Dart 模型&#xff0c;要求严格如下&#xff1a;1. 使用 json_annotation 包&#xff0c;包含&#xff1a…

【秋招笔试】2025.08.30科大讯飞秋招笔试题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围在线刷题 bishipass.com 科大讯飞 题目一:物品种类统计 1️⃣:使用集合或哈希表统计不同物品编号的数量 2️⃣:利用数学公式 n - 不同种类数 计算最终答案 难度:简单 这道题目的关…

AI 智能体汇总,自动执行任务的“真 Agent”

AI Agent 正在掀起一场静默的效率革命&#xff1a;当 AI 遇上 RPA&#xff0c;真正的“数字员工”时代已经到来最近一段时间&#xff0c;我密集关注了多场 AI Agent&#xff08;智能体&#xff09;的发布会&#xff0c;覆盖了从消费级到企业级的各类产品。一个越来越清晰的趋势…

vue布局

给于2个div块状元素的布局方案1&#xff1a;横向并排&#xff08;Flex Row&#xff09;<template><div class"container"><div class"background">背景</div><div class"panel">内容</div></div> <…

Hysplit大气传输和污染扩散-轨迹聚合标准20%30%用途

1、HYSPLIT轨迹聚合中的百分比标准在HYSPLIT模型中&#xff0c;轨迹聚合&#xff08;Trajectory Clustering&#xff09;用于将大量轨迹按相似性分组&#xff0c;20%和30%是常见的聚合阈值标准&#xff0c;反映轨迹间的空间相似度要求。2、20%和30%的具体含义这两个百分比代表轨…

Linux shell 脚本基础 003

目录 Linux shell 脚本语句 1. for 循环流程控制 1.1 基本语法格式 1.2 常见用法示例 1.3生产案例示例 2. while 循环 2.1 基本语法格式 2.2 常见用法示例 3. case 语句 3.1 基本语法格式 3.2 常见用法示例 3.3生产案例示例 4. shell 函数 4.1 函数的定义 4.2 函…

7.1elementplus的表单

Element Plus 表单由以下几个关键部分构成&#xff1a;<el-form>: 表单容器。它是整个表单的根组件&#xff0c;负责管理表单数据、校验规则、布局方式等。<el-form-item>: 表单项容器。用于包裹一个具体的表单控件&#xff08;如输入框、选择器等&#xff09;及其…

TF-IDF:文本分析的“火眼金睛”

TF-IDF&#xff1a;文本分析的“火眼金睛” 在信息爆炸的时代&#xff0c;我们每天都会接触到海量的文本数据。如何从这些数据中快速找出最重要的信息&#xff1f;TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;算法就是一种非常实用的工具&#xf…

传统星型拓扑结构的5G,WiFi无线通信网络与替代拓扑结构自组网

一、个人理解 区别自组网&#xff0c;5G和WiFi三者要抓住两个关键点&#xff1a;移动、组网。 5G通信是移动通信的最新一代&#xff1b;1940年代美军的手持对讲机虽然可以移动&#xff0c;但是算不上网络&#xff0c;后面的第一代移动通信蜂窝网络才能算上网络。 WiFi通信虽…

REST API 是无状态的吗,如何保障 API 的安全调用?

当然&#xff0c;这是一个非常核心的API设计和安全领域的问题。我们来详细拆解一下。1. REST API 是无状态的吗&#xff1f;​是的&#xff0c;REST API 的核心原则之一就是“无状态”&#xff08;Statelessness&#xff09;。​​这意味着&#xff1a;​服务器不保存客户端的会…

Machine Learning HW3 report:图像分类(Hongyi Lee)

任务&#xff1a;使用CNN把食物图片分为11类&#xff08;不能使用预训练的模型&#xff09;。此任务很耗时&#xff0c;一次训练至少1h&#xff0c;所以要利用好Kaggle notebook中Save Version功能&#xff0c;并行训练节省时间。 基准 Simple : 0.50099Medium : 0.73207 Train…

Element整体操作样式

Element: 给表格整体设置斑马纹 在main.js中 ElementUI.Table.props.stripe {type: Boolean,default: true }在element-ui.scss中 // // 为所有 el-table 设置默认斑马纹 // .el-table { // &.el-table--enable-row-hover .el-table__body tr:hover > td { // ba…

谷歌官宣组建“网络攻击部门”,美国网络安全战略转向“以攻代防”

谷歌宣布将组建网络攻击部门8月27日&#xff0c;谷歌宣布将组建网络攻击部门&#xff08;disruption unit&#xff09;。谷歌威胁情报集团副总裁Sandra Joyce在本周二的网络安全政策会议上表示&#xff0c;谷歌正在寻找“合法且符合道德规范的干扰方案”&#xff0c;通过情报主…