Spring中基于事件监听驱动 和 线程池的异步任务
文章目录
- 事件监听驱动 与 异步
- 事件源
- ApplicationContextAware接口
- 发布事件
- 事件实体
- 监听事件
- 实现异步
- 注入綫程池
- 事件驱动机制,与MQ消息队列比较
事件监听驱动 与 异步
事件监听驱动优点:解耦,将 事件和业务进行解耦,通过@Asyc注解可以实现异步
事件监听驱动优点:解耦,将 事件和业务进行解耦,通过@Asyc注解可以实现异步
我们监听事件之前要有事件源source,事件(Event),发布事件(publishEvent),然后才能到监听事件。
事件驱动机制是观察者模式(称发布订阅)具体实现,事件对象(Event)相当于被观察对象(Subject), 事件监听(EventListener) 相当于观察者(Observer)
事件源
实现ApplicationContextAware接口
重写setApplicationContext方法
获取ApplicationContext对象
public class FilePhysicalDeleteEventListener implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}
ApplicationContextAware接口
ApplicationContext作用具体参考 https://blog.csdn.net/Pluto372/article/details/130139628
在Spring/SpringMVC中,我们拿到IOC容器无非有三种方式,那就是使用ApplicationContext接口下的三个实现类:ClassPathXmlApplicationContext
、FileSystemXmlApplicationContext
、AnnotationConfigApplicationContext
。
但是SpringBoot的强大让我们无需再配置xml文件,也因此我们无法通过上述方式拿到ApplicationContext对象,所以当在项目需要用到spring中的bean对象时,一般做法就是实现ApplicationContextAware
接口,通过这个接口就可以获取到ApplicationContext对象,进入从ApplicationContext
中获取所需要bean对象。
总结:通过ApplicationContextAware接口获取ApplicationContext对象,ApplicationContext可以获取IOC容器中的bean
发布事件
通过ApplicationContext对象发布
private void physicalDeleteFileByStorageEngine(List<RPanFile> realFileRecords) {//映射为路径集合List<String> realFilePathList = realFileRecords.stream().map(RPanFile::getRealPath).collect(Collectors.toList());DeleteFileContext context = new DeleteFileContext();context.setRealFilePathList(realFilePathList);try {storageEngine.delete(context);} catch (IOException e) {//记录错误日志applicationContext.publishEvent(new ErrorLogEvent(this, "实体文件:" + JSON.toJSONString(realFilePathList) + ", 物理删除失败,请执行手动删除", RPanConstants.ZERO_LONG));}}
事件实体
事件实体需要继承ApplicationEvent对象
@Getter
@Setter
@EqualsAndHashCode
@ToString
public class ErrorLogEvent extends ApplicationEvent {/*** 错误日志的内容*/private String errorMsg;/*** 当前登录的用户ID*/private Long userId;public ErrorLogEvent(Object source, String errorMsg, Long userId) {super(source);this.errorMsg = errorMsg;this.userId = userId;}
}
监听事件
注解@EventListener(ErrorLogEvent.class)方式监听事件
@Component
public class ErrorLogEventListener {@Autowiredprivate IErrorLogService iErrorLogService;/*** 监听系统错误日志事件,并保存到数据库中** @param event*/@EventListener(ErrorLogEvent.class) //监听这个事件@Async(value = "eventListenerTaskExecutor")public void saveErrorLog(ErrorLogEvent event){RPanErrorLog record = new RPanErrorLog();//保存到数据库,调用mp 方法iErrorLogService.save(record);}
}
实现异步
实现异步,并指定线程池任务执行器,value
为指定线程池执行器的 bean的名称。
@Async(value = “eventListenerTaskExecutor”)
当 ErrorLogEvent 事件发生时,相关的处理方法将会以异步的方式执行,
并且将使用指定的任务执行器 “eventListenerTaskExecutor”。不阻塞主线程,提高响应。
public class ErrorLogEventListener {@Autowiredprivate IErrorLogService iErrorLogService;/*** 监听系统错误日志事件,并保存到数据库中** @param event*/@EventListener(ErrorLogEvent.class) //监听这个事件@Async(value = "eventListenerTaskExecutor")public void saveErrorLog(ErrorLogEvent event){RPanErrorLog record = new RPanErrorLog();//保存到数据库,调用mp 方法iErrorLogService.save(record);}
}
注入綫程池
通过Configuration注解和Bean注解以配置类的方式注入线程池
,通过name属性指定bean的名称
@SpringBootConfiguration
public class TreadPoolConfig {// 注入bean// 任务线程池执行器@Bean(name = "eventListenerTaskExecutor")public ThreadPoolTaskExecutor eventListenerTaskExecutor(){ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// new FutureTask<>();taskExecutor.setCorePoolSize(10);taskExecutor.setMaxPoolSize(10);taskExecutor.setKeepAliveSeconds(200);taskExecutor.setQueueCapacity(2048);taskExecutor.setThreadNamePrefix("event-listener-thread");//拒绝策略// CallerRunsPolicy 既不抛弃任务也不抛出异常,直接使用主线程来执行此任务// abort 直接拒绝并抛异常// discard 丢弃不抛出异常// discardEldest 抛弃队列中等待最久的taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return taskExecutor;}
}
事件驱动机制,与MQ消息队列比较
MQ驱动的作用:解耦、异步、削峰
优点:解耦,异步,削峰,消息不丢失,解决高并发消息
缺点:难维护
事件驱动机制:解耦、异步,做不到削峰。
优点:维护简单
缺点:大并发扛不住,适合单机环境,消息可能丢失,无法削峰
总结MQ的优点
- 异步解耦
- 应对高并发的消息
- 适用于分布式环境
- 消息不丢失
- 对消息进行 削峰
总结MQ的缺点:
- 分布式场景下引发的复杂问题,如分布式事务等。
相关文章:
Spring中基于事件监听驱动 和 线程池的异步任务
文章目录 事件监听驱动 与 异步事件源ApplicationContextAware接口 发布事件事件实体监听事件实现异步注入綫程池 事件驱动机制,与MQ消息队列比较 事件监听驱动 与 异步 事件监听驱动优点:解耦,将 事件和业务进行解耦,通过Asyc注解…...

C++ 优先级队列用法详解与模拟实现
文章目录 C 优先级队列用法与模拟实现介绍用法头文件1.创建优先级队列priority_queue 2. 插入元素push 3. 删除元素pop 访问顶部元素top 检查优先级队列的大小size 检查优先级队列是否为空empty 模拟实现 C 优先级队列用法与模拟实现 介绍 优先级队列(Priority Qu…...
Linux进阶之旅:深入探索Linux的高级功能
文章目录 Linux进阶之旅:深入探索Linux的高级功能1. Shell脚本编程2. 进程管理3. 网络管理4. 文本处理5. 系统监控6. 总结 Linux进阶之旅:深入探索Linux的高级功能 在上一篇博客中,我们对Linux操作系统进行了入门级的介绍,包括Linux的特点、发行版、安装方法以及基本使用。接下…...

【Java】内存可见性问题是什么?
文章目录 内存模型内存可见性解决方案volatile 内存模型 什么是JAVA 内存模型? Java Memory Model (JAVA 内存模型)是描述线程之间如何通过内存(memory)来进行交互。 具体说来, JVM中存在一个主存区(Main Memory或Java Heap Mem…...

Guava里一些比较常用的工具
随着java版本的更新提供了越来越多的语法和工具来简化日常开发,但是我们一般用的比较早的版本所以体验不到。这时就用到了guava这个包。guava提供了很多方便的工具方法,solar框架就依赖了guava的16.0.1版本,这里稍微介绍下。 一、集合工具类…...
在windows系统中【.gz.tar】和【.whl】文件分别应该怎么下载到conda的某个虚拟环境中
在 Windows 系统中,你可以按照以下步骤将 .gz.tar 和 .whl 文件下载到 Conda 的某个虚拟环境中: 激活虚拟环境:打开 Anaconda Prompt 或者命令行窗口,使用以下命令激活你想要安装文件的虚拟环境: conda activate <虚…...
Rust - 数据类型
Rust 是静态编译语言,在编译时必须知道所有变量的类型。 基于使用的值,编译器通常能推断出它的具体类型,但如果可能的类型比较多,例如把String转换为整数的parse方法,就必须添加类型的标注,否则编译会报错…...

基于springboot实现洗衣店订单管理系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现洗衣店订单管理系统演示 摘要 随着信息互联网信息的飞速发展,无纸化作业变成了一种趋势,针对这个问题开发一个专门适应洗衣店业务新的交流形式的网站。本文介绍了洗衣店订单管理系统的开发全过程。通过分析企业对于洗衣店订单管理系统…...
Java基础知识总结(53)
(1)集合框架概述 Java集合大致分为List、Set、Map和Queue Collection是一个顶级接口,其子接口有,List、Set、Queue List:有序(存放和取出顺序是一致的)、有索引、可重复 Set:无序、无索引、不可重复 &…...

196算法之谜在 JSP 中使用内置对象 request 获取 form 表单的文本框 text 提交的数据。
(1)编写 inputNumber . jsp ,该页面提供一个 form 表单,该 form 表单提供一个文本框 text ,用于用户输入一个正整数,用户在 form 表单中输入的数字,单击 submit 提交键将正整数提交给 huiwenNumber . jsp 页…...
初识责任链模式--一起学习吧之数据库
一、定义 责任链模式是一种对象行为型模式,用于处理请求发送者和多个请求处理者之间的耦合问题。在这种模式中,请求的处理者通过前一对象记住其下一个对象的引用而连成一条链。当有请求发生时,请求会沿着这条链传递,直到有对象处…...

解决Xshell登录云服务器的免密码和云服务器生成子用户问题
Xshell登录云服务器的免密码问题 前言一、Xshell登录云服务器的免密码操作实践 二、centos创建用户创建用户实操删除用户更改用户密码直接删除子用户 前言 Xshell登录云服务器免密码问题的解决方案通常涉及使用SSH密钥对。用户生成一对密钥(公钥和私钥)…...
webRtc生产环境实用方法
最近做了几个项目发现多个项目反反复复会出现几个高频的需求, 都依赖于获取系统采集设备和指定设备id获取媒体流;为了不在反复书写总结2个公用方法; 检索当前系统所有可用设备 /*** 检索当前系统所有可用设备* returns {* audioInputOption…...

Java String、StringBuffer
构造方法 通过字符数组构造,结果abc 通过字节数组构造,结果abc //把字符串转化为字节数组 当前代码编译环境为UTF-8,出现异常时,直接抛出异常即可。mainthrows UnsupportedEncodingException 编译环境为UTF-8,但是运用gb2312这个…...
LangChain调用tool集的原理剖析(包懂)
一、需求背景 在聊天场景中,针对用户的问题我们希望把问题逐一分解,每一步用一个工具得到分步答案,然后根据这个中间答案继续思考,再使用下一个工具得到另一个分步答案,直到最终得到想要的结果。 这个场景非常匹配la…...

如何正确使用数字化仪前端信号调理?(一)
一、前言 板卡式的数字转换器和类似测量仪器,比如图1所示的德思特TS-M4i系列,都需要为各种各样的特性信号与内部模数转换器(ADC)的固定输入范围做匹配。 图1:德思特TS-M4i系列高速数字化仪,包括2或4通道版…...

实验5 流程图和盒图ns图
一、实验目的 通过绘制流程图和盒图,熟练掌握流程图和盒图的基本原理。 能对简单问题进行流程图和盒图的分析,独立地完成流程图和盒图设计。 二、实验项目内容(实验题目) 1、用Microsoft Visio绘制下列程序的程序流程图。 若…...

[Java、Android面试]_18_详解Handler机制 常见handler面试题(非常重要,非常高频!!)
本人今年参加了很多面试,也有幸拿到了一些大厂的offer,整理了众多面试资料,后续还会分享众多面试资料。 整理成了面试系列,由于时间有限,每天整理一点,后续会陆续分享出来,感兴趣的朋友可关注收…...

国内开通gpt会员方法
ChatGPT镜像 今天在知乎看到一个问题:“平民不参与内测的话没有账号还有机会使用ChatGPT吗?” 从去年GPT大火到现在,关于GPT的消息铺天盖地,真要有心想要去用,途径很多,别的不说,国内GPT的镜像…...

使用 Meltano 将数据从 Snowflake 导入到 Elasticsearch:开发者之旅
作者:来自 Elastic Dmitrii Burlutskii 在 Elastic 的搜索团队中,我们一直在探索不同的 ETL 工具以及如何利用它们将数据传输到 Elasticsearch,并在传输的数据上实现 AI 助力搜索。今天,我想与大家分享我们与 Meltano 生态系统以及…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...