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接口下的三个实现类:ClassPathXmlApplicationContextFileSystemXmlApplicationContextAnnotationConfigApplicationContext
但是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的优点

  1. 异步解耦
  2. 应对高并发的消息
  3. 适用于分布式环境
  4. 消息不丢失
  5. 对消息进行 削峰

总结MQ的缺点:

  1. 分布式场景下引发的复杂问题,如分布式事务等。

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

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

相关文章

React 组件生命周期函数的用法和示例代码

React 中的生命周期函数可以分为三个阶段&#xff1a;Mounting&#xff08;挂载&#xff09;&#xff0c;Updating&#xff08;更新&#xff09;和 Unmounting&#xff08;卸载&#xff09;。每个阶段都有不同的函数&#xff0c;用于执行不同的操作。 Mounting&#xff08;挂载…

C++解决大学课设所有管理系统(增删查改)

C一篇解决大学课设所有**管理系统(增删查改) 文章目录 C一篇解决大学课设所有**管理系统(增删查改)1.引言1.1 使用结果展示 2. 基本原理3. 文件层次结构4.具体实现(通讯录管理系统为例)4.1 通讯录实体类(addressbook.h)4.2 通讯录实现类(addressbook.cpp)4.3 通讯录管理类&…

设备树的概念及引入、设备树如何变成device

在平台总线驱动模型中资源和驱动已经从逻辑上和代码组织上进行了分离&#xff0c;但每次调整资源还是会涉及到内核&#xff0c;所以现在更加流行的是设备树方式。设备树的好处是通过独立于内核存在&#xff0c;这样如果设备上外设功能启用与否以及位置变动的话很多时候不用修改…

【股权激励】“三级股权分配法”——某互联网电商企业股权激励管理

【客户背景及面临难题】K公司于2014年上线&#xff0c;是由多位创始人联合创办的一家以众包微物流配送为核心模式&#xff0c;主营同城水果、蔬菜、生鲜、日常生活用品、零食等商品在线销售&#xff0c;专注于社区生鲜最后一公里配送&#xff0c;主打一小时之内闪电送达的互联网…

Vue自定义指令介绍及使用方法

介绍​ 除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外&#xff0c;Vue 还允许你注册自定义的指令 (Custom Directives)。 之前已经介绍了两种在 Vue 中重用代码的方式&#xff1a;组件 和 组合式函数。组件是主要的构建模块&#xff0c;而组合式函数则侧重于有状态…

使用C语言函数对数组进行操作

前言 在我们了解数组和函数之后&#xff0c;我们对数组和函数进行结合&#xff0c;之后完成一些操作吧 题目描述 杰克想将函数与数组结合进行一些操作&#xff0c;以下是他想要达到的效果&#xff0c;请你帮帮他吧&#xff01; 创建一个整型数组&#xff0c;完成对数组的操作 1…

签约速递 | 看零信任如何打造安全互联的数字底座?

近期&#xff0c;易安联再传佳音&#xff0c;签约南通市公安局、隆基绿能科技股份有限公司、南京体育学院等&#xff0c;持续为客户提供功能更完善、体验更好的零信任安全解决方案&#xff0c;赋能千行百业数字化转型升级&#xff0c;共创网络安全繁荣生态。 南通市公安局 数字…

c语言:getchar()和getch()的区别

1.getchar( ): 使用getchar( )函数读取键盘输入时&#xff0c;只有用户敲击回车键后&#xff0c;getchar( )函数才会返回字符。getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区(输入缓冲区)中.直到用户按回车为止(回车字…

K-means聚类算法的原理、应用与实例

文章目录 K-means 聚类算法&#xff1a;原理K-means 聚类算法的应用K-means 聚类算法的优化与改进 一个使用 K-means 聚类算法进行客户细分的简单实例 K-means 聚类算法&#xff1a;原理 K-means 算法是一种经典的无监督学习方法&#xff0c;用于对未标记的数据集进行分群&…

智慧公厕是智慧城市建设中不可或缺的一部分

智慧城市的数字化转型正在取得显著成效&#xff0c;各项基础设施的建设也在迅速发展&#xff0c;其中智慧公厕成为了智慧城市体系中不可或缺的一部分。作为社会生活中必要的设施&#xff0c;公共厕所的信息化、数字化、智慧化升级转型能够实现全区域公共厕所管理的横向打通和纵…

数据处理-pandas之多sheet专题

pandas读取具有多个sheet的xlsx文件 import pandas as pddf1 pd.read_excel(data_path, sheet_nameNone) df2 pd.read_excel(data_path) print(df1.keys()) print(df2.keys())两个print不一样&#xff0c;如果不设定sheet_name为None&#xff0c;默认指读取一个sheet&#x…

PostgreSQL介绍

PostgreSQL是一个高度先进的对象关系型数据库管理系&#xff08;ORDBMS&#xff09;&#xff0c;其起源可以追溯到1986年&#xff0c;最初是加州大学伯克利分校计算机系的一个项目&#xff0c;名为POSTGRES。它是从Ingres项目演变而来的&#xff0c;目的是克服当时关系数据库系…

macOS 启动 Nacos(2),50家大厂面试万字精华总结

进来之后一定要选择支持 arm64 的版本不然会出现因为版本不支持导致无法启动 WARNING: The requested images platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested点击 copy docker pull nacos/naco…

Blender2.83 下载地址及安装教程

Blender是一款开源的3D计算机图形软件&#xff0c;广泛应用于动画制作、游戏开发、建模、渲染等领域。它提供了一套强大的工具和功能&#xff0c;让用户能够进行三维建模、动画制作和视觉效果的创作。 Blender支持多种文件格式的导入和导出&#xff0c;使用户能够与其他软件进…

Java中的Lambda表达式和例子

在Java中&#xff0c;Lambda表达式是一种简洁地表示实例化一个只有一个抽象方法的接口&#xff08;函数式接口&#xff09;的方式。它使得代码更加简洁和易读&#xff0c;特别是在处理函数式编程和集合操作时。Lambda表达式的主要组成部分包括参数列表、箭头&#xff08;->&…

Redis从入门到精通(七)Redis实战(四)库存超卖、一人一单与Redis分布式锁

↑↑↑请在文章开头处下载测试项目源代码↑↑↑ 文章目录 前言4.3 优惠券秒杀4.3.4 库存超卖问题及其解决4.3.4.1 问题分析4.3.4.2 问题解决 4.3.5 一人一单需求4.3.5.1 需求分析4.3.5.2 代码实现4.3.5.3 并发问题4.3.5.4 悲观锁解决并发问题4.3.5.5 集群环境下的并发问题 4.4 …

最新版手机软件App下载排行网站源码/App应用商店源码

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 一款简洁蓝色的手机软件应用app下载排行&#xff0c;app下载平台&#xff0c;最新手机app发布网站响应式织梦模板。 主要有&#xff1a;主页、app列表页、app介绍详情页、新闻资讯列…

Linux中磁盘的分区,格式化,挂载和文件系统的修复

一.分区工具 1.分区工具介绍 fdisk 2t及以下分区 推荐 (分完区不保存不生效&#xff0c;有反悔的可能) gdisk 全支持 推荐 parted 全支持 不推荐 ( 即时生效&#xff0c;分完立即生效) 2.fdisk 分区,查看磁盘 格式:fdisk -l [磁盘设备] fdisk -l 查看…

网络协议——RSTP(快速生成树)与MSTP(多实例生成树)

一. RSTP 1. STP的不足 1、依靠计时器超时的方式进行收敛导致它的收敛时间需要30到50秒 2、端口状态和端口角色没有细致区分&#xff0c;指导数据转发依靠的不是端口状态而是端口所扮演角色。 3、如果拓扑频繁变化导致用户通信质量差&#xff0c;甚至通信中断&#xf…

详解cmake简单语法与使用

注意&#xff1a;这是一篇cmake入门浅显的文章&#xff0c;深入学习的话没必要阅读。 CMake的使用流程及其语法非常丰富&#xff08;其实就是过于灵活&#xff0c;一个项目一个风格&#xff0c;看上去相当麻烦&#xff09;&#xff0c;下面逐步介绍一些核心概念和常用命令&…