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

Spring的ApplicationEvent简单使用

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。

创建Event事件

public class MessageEvent extends ApplicationEvent {/*** 消息体*/private MessageDTO messageDTO;/*** Create a new ApplicationEvent.** @param source the object on which the event initially occurred (never {@code null})*/public MessageEvent(MessageDTO source) {super(source);this.messageDTO = source;}public MessageDTO getMessageDTO() {return messageDTO;}
}

我们自定义事件MessageEvent继承了ApplicationEvent,继承后必须重载构造函数,构造函数的参数可以任意指定,其中source参数指的是发生事件的对象,该对象可以在监听内被获取。

在Spring内部中有多种方式实现监听如:@EventListener注解、实现ApplicationListener泛型接口、实现SmartApplicationListener接口等,我们下面来讲解下这三种方式分别如何实现。

创建MessageDTO

public class MessageDTO {/*** 消息类型*/private MsgTypeEnum msgType;/*** 消息发出时的时间戳*/private Long syncTime;
}

事件发布

@Service
public class UserService
{@AutowiredApplicationContext applicationContext;public void register(){//../省略其他逻辑//发布事件applicationContext.publishEvent(new MessageEvent(new MessageDTO()));}
}

事件发布是由ApplicationContext对象管控的,我们发布事件前需要注入ApplicationContext对象调用publishEvent方法完成事件发布。

实现监听

@EventListener

@Service
public class MessageEventService {@EventListenerpublic void notify(MessageEvent messageEvent) {log.info("异步发送消息体:{}", JSON.toJSONString(messageEvent));}
}

ApplicationListener

@Component
public class RegisterListener implements ApplicationListener<MessageEvent>
{/*** 实现监听*/@Overridepublic void onApplicationEvent(MessageEvent messageEvent) {}
}

SmartApplicationListener实现有序监听

@Component
public class UserRegisterListener implements SmartApplicationListener
{/***  该方法返回true&supportsSourceType同样返回true时,才会调用该监听内的onApplicationEvent方法* @param aClass 接收到的监听事件类型* @return*/@Overridepublic boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {//只有MessageEvent监听类型才会执行下面逻辑return aClass == MessageEvent.class;}/***  该方法返回true&supportsEventType同样返回true时,才会调用该监听内的onApplicationEvent方法* @param aClass* @return*/@Overridepublic boolean supportsSourceType(Class<?> aClass) {//只有在UserService内发布的MessageEvent事件时才会执行下面逻辑return aClass == UserService.class;}/***  supportsEventType & supportsSourceType 两个方法返回true时调用该方法执行业务逻辑* @param applicationEvent 具体监听实例,这里是UserRegisterEvent*/@Overridepublic void onApplicationEvent(ApplicationEvent applicationEvent) {//转换事件类型MessageEvent messageEvent = (MessageEvent) applicationEvent;}/*** 同步情况下监听执行的顺序* @return*/@Overridepublic int getOrder() {return 0;}
}

SmartApplicationListener接口继承了全局监听ApplicationListener,并且泛型对象使用的ApplicationEvent来作为全局监听,可以理解为使用SmartApplicationListener作为监听父接口的实现,监听所有事件发布。

既然是监听所有的事件发布,那么SmartApplicationListener接口添加了两个方法supportsEventType、supportsSourceType来作为区分是否是我们监听的事件,只有这两个方法同时返回true时才会执行onApplicationEvent方法。

可以看到除了上面的方法,还提供了一个getOrder方法,这个方法就可以解决执行监听的顺序问题,return的数值越小证明优先级越高,执行顺序越靠前。

如果说我们不希望在执行监听时等待监听业务逻辑耗时,发布监听后立即要对接口或者界面做出反映,我们该怎么做呢?

 使用@Async实现异步监听

@Aysnc其实是Spring内的一个组件,可以完成对类内单个或者多个方法实现异步调用,这样可以大大的节省等待耗时。内部实现机制是线程池任务ThreadPoolTaskExecutor,通过线程池来对配置@Async的方法或者类做出执行动作。

线程任务池配置

我们创建一个ListenerAsyncConfiguration,并且使用@EnableAsync注解开启支持异步处理,具体代码如下所示:

@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer
{/*** 获取异步线程池执行对象* @return*/@Overridepublic Executor getAsyncExecutor() {//使用Spring内置线程池任务对象ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();//设置线程池参数taskExecutor.setCorePoolSize(5);taskExecutor.setMaxPoolSize(10);taskExecutor.setQueueCapacity(25);taskExecutor.initialize();return taskExecutor;}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return null;}
}

我们自定义的监听异步配置类实现了AsyncConfigurer接口并且实现内getAsyncExecutor方法以提供线程任务池对象的获取。
我们只需要在异步方法上添加@Async注解就可以实现方法的异步调用

@Service
public class MessageEventService {@EventListener@Asyncpublic void notify(MessageEvent messageEvent) {log.info("异步发送消息体:{}", JSON.toJSONString(messageEvent));}
}

相关文章:

Spring的ApplicationEvent简单使用

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现&#xff0c;内部实现原理是观察者设计模式&#xff0c;设计初衷也是为了系统业务逻辑之间的解耦&#xff0c;提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听&#xff0c;监听具体的实现…...

python程序员面试题之:set vs tuple vs list vs dict

首先&#xff0c;set/tuple/list/dict都是存储变量的python类型&#xff0c;四者之间有异有同。 首先&#xff0c;set存储无序不重复序列。 set_b {1,2,4} print(set_b[0]) TypeError: ‘set’ object is not subscriptable set 会自动去重&#xff0c;所以根据这个特性可以对…...

STM32 F103C8T6学习笔记11:RTC实时时钟—OLED手表日历

之前在 学习笔记10文章 做了一个简易的&#xff0c;使用定时器计时的简单时钟&#xff0c;现在使用RTC实时时钟同步代替定时器来实现一下OLED手表日历&#xff0c;接着上个实验文章进行完善~~ 文章提供源码、测试工程下载、测试效果图。 目录 RTC实时时钟&#xff1a; 简介&…...

无法将“环境变量”项识别为 cmdlet、函数、脚本文件或可运行程序的名称(pycharm)

无法将“配置的任何一个环境变量”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 记录解决“无法将“C:......conda.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称”以及“表达式或语句中包含意外的标记”的系列问题(VSCode开发环境)一、Conda.exe无法正常识…...

基于图像链接的批量下载

1. 获取图像路径 1.1 给定图像链接&#xff0c;这是一张图像 image_url “https://univs-news-1256833609.cos.ap-beijing.myqcloud.com/123/upload/resources/image/7467914.jpg”1.1通过网站规则得到其想要的图像链接 image_urls [ f"https://univs-news-125683360…...

mongodb使用心得

入门 术语 collection&#xff1a;相当于db的表 document&#xff1a;相当于表的记录 启动 单机模式启动mongo server mongod --dbpath D:\programs\mongodb-4.2.8\data\dbreplica set模式启动 replica set模式其实就是主从模式。 做mongo的启动配置文件&#xff1a; …...

学习Vue:响应式原理与性能优化策略

性能优化是Vue.js应用开发中的一个关键方面&#xff0c;而深入了解响应式原理并采用有效的性能优化策略可以显著提升应用的性能。本文将解释响应式原理并介绍一些性能优化策略&#xff0c;旨在帮助您构建高性能的Vue.js应用。 响应式原理 Vue.js的响应式原理是通过利用Object.…...

神经网络基础-神经网络补充概念-43-梯度下降法

概念 梯度下降法&#xff08;Gradient Descent&#xff09;是一种优化算法&#xff0c;用于在机器学习和深度学习中最小化&#xff08;或最大化&#xff09;目标函数。它通过迭代地调整模型参数&#xff0c;沿着梯度方向更新参数&#xff0c;以逐步接近目标函数的最优解。梯度…...

Reids之Set类型解读

目录 基本介绍 命令概述 SADD key member1 [member2] SCARD key SINTER key1 [key2] SMEMBERS key SPOP key SUNION key1 [key2] 基本介绍 新的存储需求&#xff1a;存储大量的数据 在查询方面提供更高的效率需要的存储结构&#xff1a;能够保存大量的数据&#x…...

【网络基础】数据链路层

【网络基础】数据链路层 文章目录 【网络基础】数据链路层1、对比网络层2、以太网2.1 基本概念2.2 类似技术2.3 以太网帧 3、MAC地址对比IP地址 4、MTU4.1 对IP协议影响4.2 对UDP协议影响4.3 对TCP协议影响4.4 地址、MTU查看 5、ARP协议5.1 协议作用5.2 协议工作流程5.3 数据报…...

云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初步使用(二)

前言&#xff1a; 在前面一篇文章云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初始安装&#xff08;一&#xff09;_华为cna_晚风_END的博客-CSDN博客 介绍了基于VMware虚拟机里嵌套部署华为云的云计算&#xff0c;不过仅仅是做到了在VRM的web界面添加计算节点…...

Python typing函式庫和torch.types

Python typing函式庫和torch.types 前言typingSequence vs IterableCallableUnionOptionalFunctionsCallableIterator/generator位置參數 &#xff06; 關鍵字參數 Classesself自定義類別ClassVar\_\_setattr\_\_ 與 \__getattr\_\_ torch.typesbuiltins 參數前的&#xff0a; …...

UE5 编程规范

官方文档 使用现代C编程标准, 使用前沿C标准库版本. 1. 类中按照先 Public 后 Private 去写 2. 继承自 UObject 的类都以 U 前缀 3. 继承自 AActor 的类都以 A 前缀 4. 继承自 SWidget 的类都以 S 前缀 5. 模板以 T 前缀 6. 接口以 I 前缀 7. 枚举以 E 前缀 8. 布尔值…...

交互消息式IMessage扩展开发记录

IMessage扩展简介 iOS10新加入的基于iMessage的应用扩展&#xff0c;可以丰富发送消息的内容。&#xff08;分享表情、图片、文字、视频、动态消息&#xff1b;一起完成任务或游戏。&#xff09; 简单的将发送的数据内型分为三种&#xff1a; 1.贴纸Stickers&#xff1b; 2.交…...

软件团队降本增效-建立需求评估体系

需求对于软件开发来说是非常重要的输入&#xff0c;它们直接决定了软件的产品形态、代码数量和质量。如果需求不清晰、不完善&#xff0c;或者存在逻辑冲突&#xff0c;将会导致软件质量迅速下降&#xff0c;增加代码耦合性和开发成本。 在开发过程中&#xff0c;对需求的产品…...

npm yarn pnpm 命令集

npm 安装依赖 npm install 安装某个依赖 npm install xxx7.6.3 安装到全局&#xff08;dependencies&#xff09; npm install xxx7.6.3 -S 安装到线下&#xff08;devDependencies&#xff09; npm install xxx7.6.3 -D 卸载某个依赖 npm uninstall xxx 卸载全局依…...

python 开发环境(PyCharm)搭建指南

Python 的下载并安装 参考&#xff1a;Python基础教程——搭建Python编程环境 下载 Python Python 下载地址&#xff1a;官网 &#xff08;1&#xff09;点击【Downloads】>>>点击【Windows】>>>点击【Python 3.x.x】下载最新版 Python&#xff1b; Pyt…...

springboot里 运用 easyexcel 导出

引入pom <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version> </dependency>运用 import com.alibaba.excel.EasyExcel; import org.springframework.stereotype.Contr…...

一“码”当先,PR大征集!2023 和RT-Thread一起赋能开源!

活动地址&#xff1a;https://club.rt-thread.org/ask/article/3c7cf7345ca47a18.html 活动介绍 「一“码”当先&#xff0c;PR大征集&#xff01;」是一项为了鼓励开发者积极参与开源软件开发维护的活动。 你可在Github RT-Thread&#xff08; https://github.com/RT-Thread …...

jmeter模拟多用户并发

一、100个真实的用户 1、一个账号模拟100虚拟用户同时登录和100账号同时登录 区别 &#xff08;1&#xff09;1个账号100个人用&#xff0c;同时登录&#xff1b; &#xff08;2&#xff09;100个人100个账号&#xff0c;同时登录。 相同 &#xff08;1&#xff09;两个都…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...