SpringEvent扩展性利器

2024-06-22 04:20

本文主要是介绍SpringEvent扩展性利器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用Spring Event机制可以保证高扩展性:

在这里插入图片描述

使用Spring Event来发布应用内部领域事件,对于事件监听器可通过注解或类的方式来扩展,Spring
Event内部使用观察者模式,但api使用层面可以完全解耦事件发布和事件监听:

在这里插入图片描述

常用方式:

@Component
@Slf4j
public class ClazzHourEventListener {// 默认同步调用该方法,@Order注解编排顺序@EventListener@Orderpublic void listener1(ClazzHourDepletedMemEvent event) {// ...}// @Async注解实现异步调用@Async@EventListenerpublic void listener2(ClazzHourDepletedMemEvent event) {// ...}// 事务监听,默认在事务提交后同步执行该方法@TransactionalEventListenerpublic void listener3(ClazzHourDepletedMemEvent event) {// ...}
}

注解实现事件监听需要考虑一下三个方面的内容:

  • 异步:如何实现异步
  • 事务:调用者的事务和监听器事务关系,包括异步情况下
  • 异常处理:异常需要捕获吗?对事务有什么影响

测试如下:

@Service
public class BizService {@AutowiredStudentMapper mapper;@AutowiredApplicationEventPublisher publisher;@Transactionalpublic void bizAction(){Student student = new Student();student.setId(120L);student.setName("test1");mapper.insert(student);System.out.println("bizAction +"+Thread.currentThread().getName());// 发布时间publisher.publishEvent(new TestEvent());}}@Component
public class TestTxListener {@AutowiredStudentMapper studentMapper;// 该步抛异常会导致后续listener无法运行// 该步事务和BizService中是一个,抛异常会同时回滚// @Order(2) @EventListenerpublic void listener1(TestEvent event){System.out.println("TestTxListener 1 +"+Thread.currentThread().getName());Student student = new Student();student.setId(121L);student.setName("同步调用测试tx");studentMapper.insert(student);// throw new RuntimeException();}// 异步 情况下 该步事务和BizService中不是一个,这里抛异常不影响其他listenr执行,也不影响BizService事务// 如果order优先级高的同步listener抛异常,这里也会执行不到// @Order(1)@Async("testTPE")@EventListenerpublic void listener2(TestEvent event){System.out.println("TestTxListener 2 +"+Thread.currentThread().getName());Student student = new Student();student.setId(122L);student.setName("异步调用测试tx");studentMapper.insert(student);// throw new RuntimeException();}
}@Component
public class TestTxListener {@AutowiredStudentMapper studentMapper;// 默认同步调用,这里面跑出异常不影响其他TransactionalEventListener执行// TransactionalEventListener 使用 TransactionSynchronization实现// 这里的事务需要指定REQUIRES_NEW,或者使用编程式事务。否则无法提交,详见TransactionSynchronization    // The transaction will have been committed already, but the // transactional resources might still be active and accessible. // As a consequence, any data access code triggered at this point // will still "participate" in the original transaction, allowing // to perform some cleanup (with no commit following anymore!), // unless it explicitly declares that it needs to run in a // separate transaction. Hence: Use PROPAGATION_REQUIRES_NEW for // any transactional operation that is called from here.// 但是,如果使用@Async,就没有这个问题,因为事务是绑定线程的,多线程propogation无作用@Transactional(propogation=REQUIRES_NEW)@Order(1)@TransactionalEventListenerpublic void listener1(TestEvent event){// 同步调用System.out.println("TestTxListener 1 +"+Thread.currentThread().getName());Student student = new Student();student.setId(161L);student.setName("同步调用测试tx");studentMapper.insert(student);// 不影响其他listener执行throw new RuntimeException();}@Order(2)// @Async 可异步@TransactionalEventListenerpublic void listener2(TestEvent event){System.out.println("TestTxListener 2 +"+Thread.currentThread().getName());Student student = new Student();student.setId(162L);student.setName("异步调用测试tx");studentMapper.insert(student);}
}

由此可见 EventListener
执行过程中遇到异常终止,则后续的同步&异步EventListener都不会执行(之前的会执行,使用@Order控制顺序),而TransactionalEventListener相互之间不受影响。所以使用EventListener要做好异常处理。此外TransactionalEventListener方法内使用事务(默认afterCommit)需要注明@Transactional(
propogation=REQUIRES_NEW)或使用编程式事务,但是如果@Async异步时,就不需要指定,因为事务是绑定线程的。

ps:

org.springframework.modulith.events.ApplicationModuleListener@Async
@Transactional(propagation=REQUIRES_NEW)
@TransactionalEventListener
@Documented
@Target({METHOD,ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface ApplicationModuleListener{@AliasFor(annotation=org.springframework.context.event.EventListener.class,attribute="id")String id();@AliasFor(annotation=org.springframework.transaction.annotation.Transactional.class,attribute="readOnly")boolean readOnlyTransaction();
}

这篇关于SpringEvent扩展性利器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1083276

相关文章

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

键盘快捷键:提高工作效率与电脑操作的利器

键盘快捷键:提高工作效率与电脑操作的利器 在数字化时代,键盘快捷键成为了提高工作效率和优化电脑操作的重要工具。无论是日常办公、图像编辑、编程开发,还是游戏娱乐,掌握键盘快捷键都能带来极大的便利。本文将详细介绍键盘快捷键的概念、重要性、以及在不同应用场景中的具体应用。 什么是键盘快捷键? 键盘快捷键,也称为热键或快捷键,是指通过按下键盘上的一组键来完成特定命令或操作的方式。这些快捷键通常涉及同

JavaScript正则表达式六大利器:`test`、`exec`、`match`、`matchAll`、`search`与`replace`详解及对比

在JavaScript中,正则表达式(Regular Expression)是一种用于文本搜索、替换、匹配和验证的强大工具。本文将深入解析与正则表达式相关的几个主要执行方法:test、exec、match、matchAll、search和replace,并对它们进行对比,帮助开发者更好地理解这些方法的使用场景和差异。 正则表达式基础 在深入解析方法之前,先简要回顾一下正则表达式的基础知识。正则

GraphPad Prism 10 for Mac/Win:高效统计分析与精美绘图的科学利器

GraphPad Prism 10 是一款专为科研工作者设计的强大统计分析与绘图软件,无论是Mac还是Windows用户,都能享受到其带来的便捷与高效。该软件广泛应用于生物医学研究、实验设计和数据分析领域,以其直观的操作界面、丰富的统计方法和多样化的图表样式,成为科学研究的得力助手。 数据处理与整理 GraphPad Prism 10 支持从多种数据源导入数据,如Excel、CSV文件及数据库

Axure元件库Ant Design中后台原型模板:提升设计与开发效率的利器

企业对于中后台产品的设计与开发需求日益增长。为了提升用户体验和开发效率,设计者和开发者们不断寻求更加高效、统一的解决方案。Ant Design,作为阿里巴巴开源的一套企业级UI设计语言和React组件库,凭借其丰富的组件和统一的设计风格,已成为众多项目的首选。而在Axure中使用Ant Design元件库,更是为中后台产品的原型设计带来了极大的便利。 Ant Design简介 Ant D

【Linux】Linux 管道:进程间通信的利器

文章目录 Linux 管道:进程间通信的利器1. 什么是管道?2. 管道的分类2.1 匿名管道(Unnamed Pipe)2.2 命名管道(Named Pipe,FIFO) 3. 管道的局限性4. 结论 Linux 管道:进程间通信的利器 在 Linux 系统中,管道(Pipe)是进程间通信(IPC, Inter-Process Communication)的重要机制之一。

保研 比赛 利器: 用AI比赛助手降维打击数学建模

数学建模作为一个热门但又具有挑战性的赛道,在保研、学分加分、简历增色等方面具有独特优势。近年来,随着AI技术的发展,特别是像GPT-4模型的应用,数学建模的比赛变得不再那么“艰深”。通过利用AI比赛助手,不仅可以大大提升团队效率,还能有效提高比赛获奖几率。本文将详细介绍如何通过AI比赛助手完成数学建模比赛,并结合实例展示其强大功能。 一、AI比赛助手的引入 1. 什么是AI比赛助手? AI比

SpringCloud:构建分布式系统的利器

引言 随着云计算和微服务架构的兴起,传统的单体应用已经难以满足现代应用的高并发、高可用、可扩展等需求。SpringCloud,作为Spring生态中的微服务架构开发工具,通过提供一系列组件和框架,帮助开发者快速构建分布式系统。本文将详细介绍SpringCloud的概念、核心组件、以及如何使用SpringCloud来搭建一个简单的微服务应用。 SpringCloud简介 SpringCloud

【机器学习 模型调参】GridSearchCV模型调参利器

导入模块sklearn.model_selection from sklearn.model_selection import GridSearchCV GridSearchCV 称为网格搜索交叉验证调参,它通过遍历传入的参数的所有排列组合,通过交叉验证的方式,返回所有参数组合下的评价指标得分,GridSearchCV 函数的参数详细解释如下: class sklearn.model_se

【爬虫神器 pyppeteer】比 selenium 更高效的爬虫利器--pyppeteer

Puppeteer 是 Google 基于 Node.js 开发的工具,调用 Chrome 的 API,通过 JavaScript 代码来操纵 Chrome 完成一些操作,用于网络爬虫、Web 程序自动测试等。pyppeteer 使用了 Python 异步协程库 asyncio,可整合 Scrapy 进行分布式爬虫。要注意的是它执行python3.6+以后版本使用,下面我们一起来了解下如何使用。