Spring Boot 事件驱动:构建灵活可扩展的应用

  在 Spring Boot 应用中,事件发布和监听机制是一种强大的工具,它允许不同的组件之间以松耦合的方式进行通信。这种机制不仅可以提高代码的可维护性和可扩展性,还能帮助我们构建更加灵活、响应式的应用。本文将深入探讨 Spring Boot 的事件发布和监听机制,揭示其工作原理,并分享一些最佳实践。

一、观察者模式的应用

  Spring Boot的事件发布与监听机制基于观察者模式(Observer Pattern),这是一种行为设计模式,其中对象之间定义了一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会自动得到通知并更新。具体来说,在Spring Boot中,ApplicationEvent作为事件对象,而ApplicationListener则充当事件监听器的角色。每当某个事件发生时,Spring容器会负责通知所有的监听器,使得它们能够根据接收到的信息执行相应的操作。

二、核心概念

  1. 事件(Event):事件是应用中发生的某个状态变化的信号。在 Spring Boot 中,事件通常是一个继承自 ApplicationEvent 的 Java 对象。事件可以是系统事件(例如,应用启动事件、关闭事件),也可以是自定义事件(例如,用户注册事件、订单创建事件)。
  2. 事件发布者(Event Publisher):事件发布者负责创建并发布事件。在 Spring Boot 中,通常通过 ApplicationEventPublisher 接口来实现事件的发布。
  3. 事件监听器(Event Listener):事件监听器负责监听特定的事件,并在事件发生时执行相应的处理逻辑。在 Spring Boot 中,通常通过 @EventListener 注解或者实现 ApplicationListener 接口来实现事件的监听。

三、实现方式

3.1 定义事件

import org.springframework.context.ApplicationEvent;public class MyCustomEvent extends ApplicationEvent {private String message;public MyCustomEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}
}

3.2 发布事件

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;@Service
public class MyService {@Autowiredprivate ApplicationEventPublisher publisher;public void doSomething() {//发布事件publisher.publishEvent(new MyCustomEvent(this, "触发自定义事件!"));}
}

3.3 监听事件

  这可以通过两种方式实现:

  • 实现ApplicationListener接口:这种方式较为传统,需要显式地实现onApplicationEvent()方法。
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;@Component
public class MyEventListener implements ApplicationListener<MyCustomEvent> {@Overridepublic void onApplicationEvent(MyCustomEvent event) {System.out.println("接收到自定义事件: " + event.getMessage());}
}

  值得注意的是,对于同步监听器而言,如果希望控制不同监听器之间的执行顺序,则可以使用@Order注解指定优先级。在不同的监听器类上面加上@Order(1)、@Order(2)、@Order(3)…即可

接收到自定义事件1: 触发自定义事件!
接收到自定义事件2: 触发自定义事件!
接收到自定义事件3: 触发自定义事件!
  • 使用@EventListener注解:这是更为简洁的做法,只需在目标方法上添加此注解即可。此外,还可以结合@Async注解实现异步监听,但需确保已启用异步支持(例如,在主类或配置类上添加@EnableAsync)。示例代码如下所示:
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;@Component
public class MyEventListener {@EventListener@Async //使用@Async注解,进行异步处理public void handleMyCustomEvent(MyCustomEvent event) {System.out.println("接收到自定义事件: " + event.getMessage());}
}

四、工作原理

  • 事件发布:当调用 ApplicationEventPublisher.publishEvent() 方法发布事件时,Spring Boot 会根据事件的类型,将事件发送给所有注册的监听器。如果配置了异步监听,则会在另外的线程处理。

  • 事件监听:Spring Boot 会在应用启动时,扫描所有带有 @EventListener 注解的方法或者实现了 ApplicationListener 接口的类,并将它们注册为事件监听器。当事件发生时,Spring Boot 会根据事件类型,调用相应的监听器的方法。监听器方法可以通过参数获取事件对象,并执行相应的处理逻辑。

五、应用场景

  1. 用户注册:用户注册成功后,发布用户注册事件,触发发送欢迎邮件、短信通知等操作。
  2. 订单创建:订单创建完成后,发布订单创建事件,触发扣减库存、发送订单通知等操作。
  3. 日志记录:应用发生异常时,发布异常事件,记录异常信息到日志文件或数据库中。
  4. 系统监控:应用启动或关闭时,发布启动或关闭事件,用于系统监控。
  5. 模块解耦:不同模块之间通过事件进行通信,实现模块之间的解耦。

六、高级特性

  除了基本的功能外,Spring Boot还提供了其他一些高级特性来丰富事件发布与监听机制的功能性:

  • 条件监听:借助SpEL表达式,我们可以为@EventListener设置条件属性,只有当满足指定条件时才会触发监听器。例如,仅当用户的名字为“张三”时才处理用户更新事件。
  • 事务感知:通过@TransactionalEventListener注解,可以使监听器的行为与事务状态相关联,默认情况下是在事务提交后执行监听器逻辑。
  • 多播器(Multicaster):在内部,Spring使用ApplicationEventMulticaster来管理和分发事件给多个监听器,确保每个监听器都能接收到正确的事件。

七、最佳实践

  1. 合理定义事件: 事件应该足够细粒度,能够准确描述应用中发生的状态变化。
  2. 避免过度使用事件:事件机制主要用于处理异步操作,对于同步操作,应该尽量使用直接方法调用。
  3. 使用事件发布者接口: 为了代码的简洁和清晰,尽量使用ApplicationEventPublisher 接口发布事件,避免手动创建事件对象。
  4. 避免在事件监听器中执行耗时操作:如果需要在事件监听器中执行耗时操作,应该将其放入单独的线程池中执行,或者使用 @Async 注解进行异步处理。
  5. 注意事件的传递:如果事件需要在不同的组件之间传递,应该考虑事件的传递效率和安全性。
  6. 测试: 编写单元测试或集成测试,确保事件发布和监听机制的正确性。
  7. 异常处理: 在事件监听器中,做好异常处理,避免影响其他业务功能,可以使用try catch 捕获异常,也可以使用@ExceptionHandler 来统一处理异常。

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

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

相关文章

PostgreSQL主从复制配置

本文主要介绍基于pg_basebackup实现主从复制&#xff08;异步流复制&#xff09; MASTER节点安装的方法可以看这篇文章 PostgreSQL YUM安装_yum install postgresql-CSDN博客 关于基本的配置就不作过多的介绍了&#xff0c;直接开始 MASTER节点 首先在master节点创建一个用于…

2025 OWASP十大智能合约漏洞

随着去中心化金融&#xff08;DeFi&#xff09;和区块链技术的不断发展&#xff0c;智能合约安全的重要性愈发凸显。在此背景下&#xff0c;开放网络应用安全项目&#xff08;OWASP&#xff09;发布了备受期待的《2025年智能合约十大漏洞》报告。 这份最新报告反映了不断演变的…

linux下使用脚本实现对进程的内存占用自动化监测

linux系统中常用cat /proc/{pid}/status和pmap -x {pid}来监测某个进程的内存资源占用情况。 其中注意各参数的含义如下&#xff1a; VmSize&#xff1a;表示进程当前虚拟内存大小 VmPeak&#xff1a;表示进程所占用最大虚拟内存大小 VmRSS&#xff1a;表示进程当前占用物理内…

双足机器人开源项目

双足机器人&#xff08;也称为人形机器人或仿人机器人&#xff09;是一个复杂的领域&#xff0c;涉及机械设计、电子工程、控制理论、计算机视觉等多个学科。对于想要探索或开发双足机器人的开发者来说&#xff0c;有许多开源项目可以提供帮助。这些项目通常包括硬件设计文件、…

关于WPF中ComboBox文本查询功能

一种方法是使用事件&#xff08;包括MVVM的绑定&#xff09; <ComboBox TextBoxBase.TextChanged"ComboBox_TextChanged" /> 然而运行时就会发现&#xff0c;这个事件在疯狂的触发&#xff0c;很频繁 在实际应用中&#xff0c;如果关联查询数据库&#xff0…

mysql之表的外键约束

MySQL表的外键约束详细介绍及代码示例 外键约束是数据库中用于维护数据完整性和一致性的重要机制。它确保一个表中的数据与另一个表中的数据相关联&#xff0c;防止无效的数据引用。本文将详细介绍了外键约束的各个方面&#xff0c;并通过具体的代码示例进行演示。 1. 外键约束…

[Qt]系统相关-网络编程-TCP、UDP、HTTP协议

目录 前言 一、UDP网络编程 1.Qt项目文件 2.UDP类 QUdpSocket QNetworkDatagram 3.UDP回显服务器案例 细节 服务器设计 客户端设计 二、TCP网络编程 1.TCP类 QTcpServer QTcpSocket 2.TCP回显服务器案例 细节 服务器设计 客户端设计 三、HTTP客户端 1.HTTP…

【LeetCode】--- MySQL刷题集合

1.组合两个表&#xff08;外连接&#xff09; select p.firstName,p.lastName,a.city,a.state from Person p left join Address a on p.personId a.personId; 以左边表为基准&#xff0c;去连接右边的表。取两表的交集和左表的全集 2.第二高的薪水 &#xff08;子查询、if…

【2024年华为OD机试】(B卷,100分)- 数据分类 (Java JS PythonC/C++)

一、问题描述 题目描述 对一个数据a进行分类,分类方法为: 此数据a(四个字节大小)的四个字节相加对一个给定的值b取模,如果得到的结果小于一个给定的值c,则数据a为有效类型,其类型为取模的值;如果得到的结果大于或者等于c,则数据a为无效类型。 比如一个数据a=0x010…

Linux:常用命令--文件与目录操作

ls命令 功能&#xff1a;&#xff08;list&#xff09;列出当前目录的文件信息 语法&#xff1a;ls [-l -h -a] [参数] 参数&#xff1a;被查看的文件夹&#xff0c;不提供参数&#xff0c;表示查看当前工作目录-l&#xff0c;以列表形式查看每个文件的属性&#xff0c;包含…

Java 8 实战 书籍知识点散记

一、Lambda表达式 1.1 Lambda表达式的一些基本概念 1.2 Lambda表达式的三个部分 // 简化前Comparator<Apple> byWeightnew Comparator<Apple>() {public int compare(Apple a1, Apple a2){return a1.getWeight().compareTo(a2.getWeight());}};//Lambda表达式Comp…

大数据中 TopK 问题的常用套路

大数据中 TopK 问题的常用套路 作者 Chunel Feng&#xff0c;编程爱好者&#xff0c;阿里巴巴搜索引擎开发工程师。开源项目&#xff1a;Caiss 智能相似搜索引擎 对于海量数据到处理经常会涉及到 topK 问题。在设计数据结构和算法的时候&#xff0c;主要需要考虑的应该是当前算…

GPU算力平台|在GPU算力平台部署MedicalGPT医疗大模型的应用教程

文章目录 一、GPU算力服务平台云端GPU算力平台 二、平台账号注册流程MedicalGPT医疗大模型的部署MedicalGPT医疗大模型概述MedicalGPT部署步骤 一、GPU算力服务平台 云端GPU算力平台 云端GPU算力平台专为GPU加速计算设计&#xff0c;是一个高性能计算中心&#xff0c;广泛应用…

计算机组成原理(计算机系统3)--实验九:多核机器上的pthread编程

一、实验目标&#xff1a; 学习多核机器上的pthread编程&#xff0c;观察SMP上多线程并发程序行为&#xff1b;了解并掌握消除SMP上cache ping-pong效应的方法&#xff1b;学习cache存储体系和NUMA内存访存特性。 二、实验内容 实验包括以下几个部分&#xff1a; 以一个计数…

Android SystemUI——最近任务应用列表(十七)

对于最近任务应用列表来说,在 Android 原生 SystemUI 中是一个单独的组件。 <string-array name="config_systemUIServiceComponents" translatable="false">……<item>com.android.systemui.recents.Recents</item> </string-arra…

【Mac】Python相关知识经验

一、给Python3安装第三方库 mac下给Python3安装第三方库pillow&#xff0c;处理图片 【安装方式】&#xff1a; 终端中输入命令&#xff1a;python3 -m pip install pillow 按回车&#xff0c;等待pillow下载安装 NOTE: 其他模块同理&#xff0c;如pytesseract 二、Python版…

Python - itertools- pairwise函数的详解

前言&#xff1a; 最近在leetcode刷题时用到了重叠对pairwise,这里就讲解一下迭代工具函数pairwise,既介绍给大家&#xff0c;同时也提醒一下自己&#xff0c;这个pairwise其实在刷题中十分有用&#xff0c;相信能帮助到你。 参考官方讲解&#xff1a;itertools --- 为高效循…

DEBERTA:具有解耦注意力机制的解码增强型BERT

摘要 近年来&#xff0c;预训练神经语言模型的进展显著提升了许多自然语言处理&#xff08;NLP&#xff09;任务的性能。本文提出了一种新的模型架构DeBERTa&#xff08;具有解耦注意力机制的解码增强型BERT&#xff09;&#xff0c;通过两种新技术改进了BERT和RoBERTa模型。第…

鸿蒙模块概念和应用启动相关类(HAP、HAR、HSP、AbilityStage、UIAbility、WindowStage、window)

目录 鸿蒙模块概念 HAP entry feature har shared 使用场景 HAP、HAR、HSP介绍 HAP、HAR、HSP开发 应用的启动 AbilityStage UIAbility WindowStage Window 拉起应用到显示到前台流程 鸿蒙模块概念 HAP hap包是手机安装的最小单元&#xff0c;1个app包含一个或…

[OpenGL]实现屏幕空间环境光遮蔽(Screen-Space Ambient Occlusion, SSAO)

一、简介 本文介绍了 屏幕空间环境光遮蔽(Screen-Space Ambient Occlusion, SSAO) 的基本概念&#xff0c;实现流程和简单的代码实现。实现 SSAO 时使用到了 OpenGL 中的延迟着色 &#xff08;Deferred shading&#xff09;技术。 按照本文代码实现后&#xff0c;可以实现以下…