Spring Event如何优雅实现系统业务解耦

Spring Event如何优雅实现系统业务解耦

一、介绍

Spring事件(Spring Event)是Spring框架的一项功能,它允许不同组件之间通过发布-订阅机制进行解耦的通信。在Spring中,事件是表示应用程序中特定事件的对象,例如用户注册、订单创建、数据更新等。当这些事件发生时,可以通知其他组件来执行相应的操作。

具体来说,Spring事件机制包含以下几个主要的部分:

1、事件(Event):
事件是一个普通的POJO类,用于封装与应用程序状态变化相关的信息。通常情况下,事件类继承自ApplicationEvent抽象类,Spring中提供了一些内置的事件,也可以自定义事件。
2、事件发布者(ApplicationEventPublisher):
事件发布者是一个接口,用于发布事件。在Spring中,ApplicationContext就是一个事件发布者,可以通过ApplicationContext的publishEvent()方法来发布事件。
3、事件监听器(ApplicationListener):
事件监听器是一个接口,用于监听事件并在事件发生时执行相应的逻辑。在Spring中,我们可以通过实现ApplicationListener接口或使用@EventListener注解来定义事件监听器。
4、 事件监听器注册:
事件监听器需要注册到事件发布者(ApplicationContext)中,以便在事件发生时被正确调用。在Spring中,通常通过XML配置、注解或者编程方式将事件监听器注册到ApplicationContext中。

设计模式:订阅发布模式

Spring Event是一种基于观察者模式(Observer Pattern)的实现。观察者模式(Observer Design
Pattern)也被称为发布订阅模式。其定义是:在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。

在这里插入图片描述

二、代码示例

Spring Boot并不会自动默认维护一个线程池来处理event事件,也就是说他的订阅发布是同步。要想异步处理事件使用 @Async标记即可,注意前提条件是:使用 @EnableAsync 开启 Spring 异步

2.1 定义实体类
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Employee {private Long id;private String userNo;private String nickname;private String email;private String phone;private Integer gender;private Date birthday;private Integer isDelete;}
2.2 自定义一个注册事件
@Getter
public class RegisterEvent extends ApplicationEvent {private Employee employee;public RegisterEvent(Object source, Employee employee) {super(source);this.employee = employee;}
}

注意这里的类名,对于多个发布事件,就是靠订阅不同的注册事件类名来区分

2.3 定义事件监听器

方法一 实现ApplicationListener接口
方法二 使用@EventListener注解。

@Slf4j
@Component // 把监听器注册到spring容器中,(这里的RegisterEvent就是指哪个发布事件)
@Async("asyncExecutor")
public class RegisterMsgNoticeListener implements ApplicationListener<RegisterEvent> {@Overridepublic void onApplicationEvent(RegisterEvent event) {log.info("=========>>>站内信通知了");}
}
@Slf4j
@Component
public class RegisterPushDataListener{//注意使用纾解的方式,@Async需加在方法上@EventListener@Async("asyncExecutor")public void onApplicationEvent(RegisterEvent event) {log.info("======>>>推送用户信息到大数据系统了,user={}", event.getUser());}
}
2.4 发布事件

实现类

@Slf4j
@Service
public class UserServiceImpl implements UserService {@Resourceprivate ApplicationContext applicationContext;@Overridepublic void registerUser(User user) {log.info("=====>>>user注册成功了");applicationContext.publishEvent(new RegisterEvent(this, user));}
}

注意:这里的ApplicationContext 是import org.springframework.context.ApplicationContext;

接口

public interface EmployeeService {void register(Employee employee);
}

控制层

@PostMapping("/register")public void register() {Employee user = Employee.builder().userNo("1111").birthday(new Date()).gender(0).phone("120").email("123@163.com").nickname("雪飘人间").build();employeeService.register(user);}
2.5 主启动类加异步线程注解
@EnableAsync
@SpringBootApplication
public class SimpleSadApplication {public static void main(String[] args) {System.out.println("系统开始启动…………");long l1 = System.currentTimeMillis();SpringApplication.run(SimpleSadApplication.class, args);long l2 = System.currentTimeMillis();System.out.println("系统启动完毕,用时:"+(l2-l1)+"毫秒!");}
}
2.6 自定义线程池
@Configuration
public class InitThreadPool {@Bean(name = "asyncExecutor")public Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(1);executor.setMaxPoolSize(5);executor.setQueueCapacity(200);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("asyncExecutor-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}
}

调用接口:可以看到,输出结果,订阅已发布也已经解耦了,但是多个订阅者的顺序是随机的

三、spring Event优缺点

优点:

简单易用: Spring Event是Spring框架提供的一个内置的事件发布-订阅机制,使用起来非常简单,无需引入额外的依赖。

无中间件依赖: Spring Event不依赖于任何消息中间件,适用于小型项目或者简单的消息通信场景。

模块解耦: Spring Event可以帮助实现模块之间的解耦,提高系统的灵活性和可维护性。

缺点:

单点问题: Spring Event是在单个应用内部的事件通知机制,如果应用崩溃或者重启,事件将会丢失。

不支持分布式: Spring Event只能在单个应用内部传递消息,不支持分布式环境下的消息传递。

性能问题: Spring Event在大规模消息通信场景下可能会存在性能问题,因为它是同步执行的,消息发布者需要等待所有订阅者处理完消息后才能继续执行

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

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

相关文章

在win11系统上安装启动Hyper-V

Hyper-V 是微软公司开发的一种虚拟化技术&#xff0c;它允许一台物理计算机运行多个操作系统和应用程序&#xff0c;从而提供更好的资源利用率和系统灵活性。 win系统的linux子系统开启、android studio的虚拟环境都需要这个东西&#xff0c;而在初始的win11系统上可能没有这个…

Nvidia/算能 +FPGA+AI大算力边缘计算盒子:电力巡检智能机器人

聚焦数字经济与双碳经济赛道&#xff0c;专注于提供集中式新能源场站与分布式综合能源数智化整体解决方案&#xff0c;坚持以场站数字化、综合能源数字化双轮驱动发展。依靠专业化人才队伍与丰富的实证基地研究经验&#xff0c;打造成熟、先进的数智新能源研发平台。 在集中式新…

Docker Swarm集群部署管理

Docker Swarm集群管理 文章目录 Docker Swarm集群管理资源列表基础环境一、安装Docker二、部署Docker Swarm集群2.1、创建Docker Swarm集群2.2、添加Worker节点到Swarm集群2.3、查看Swarm集群中Node节点的详细状态信息 三、Docker Swarm管理3.1、案例概述3.2、Docker Swarm中的…

【Web世界探险家】3. CSS美学(二)文本样式

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 |《MySQL探索之旅》 |《Web世界探险家》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更…

基于深度学习的中文语音识别模型(支持wav、mp4、m4a等所有格式音频上传)【已开源】

基于深度学习的中文语音识别模型&#xff08;支持wav、mp4、m4a等所有格式音频上传&#xff09; 前言 该开源项目旨在提供一个能够自动检测并识别中文语音的模型&#xff0c;支持wav、mp4、m4a等格式的音频文件上传。无论是从录音设备中获取的wav文件&#xff0c;还是从视频中…

外部排序快速入门详解:基本原理,败者树,置换-选择排序,最佳归并树

文章目录 外部排序1.最基本的外部排序原理2.外部排序的优化2.1 败者树优化方法2.2 置换-选择排序优化方法2.3 最佳归并树 外部排序 为什么要学习外部排序&#xff1f; 答&#xff1a; 在处理数据的过程中&#xff0c;我们需要把磁盘(外存&#xff09;中存储的数据拿到内存中处理…

ue5创建地图瓦片

先在虚幻商城下载免费的paperzd插件&#xff0c;并启用。 导入资源后&#xff0c;先通过应用paper2d纹理资源&#xff0c;将去掉导入ue时产生的边缘模糊&#xff0c;再点击下面的创建瓦片集&#xff0c; 打开瓦片集&#xff0c;发现选中不对&#xff0c; 改变瓦片大小为16*…

ChatGPT对话基本原则和玩法

一、使用三个准备 1.1 认知上 超级学霸&#xff0c;几乎所有的工作/生活场景&#xff0c;都可以找它帮忙 ChatGPT作为一个人工智能语言模型&#xff0c;具有强大的知识储备和处理能力。这意味着在许多工作和生活场景中&#xff0c;你都可以向它请教问题或寻求帮助。无论是科…

Virustotal查询恶意进程

1、使用netstat查看可疑进程 执行ls -al /proc/$PID/exe确认可疑进程对应的文件&#xff1b;若文件未被删除&#xff0c;则直接上传文件到Virustotal进行检测&#xff0c;或者计算出文件对应的md5&#xff0c;使用md5去Virustotal进行查询&#xff1b;若文件已被删除&#xff0…

Python第二语言(七、Python模块)

目录 1. 什么是模块 2. 基本语法 2.1 模块的导入方式 2.2 基本语法 import 模块名 2.3 基本语法 from 模块名 import 功能名 2.4 基本语法as 别名 3. 自定义模块 4. 调用自定义模块时&#xff0c;如何让其模块中的函数不被调用&#xff08;__name__&#xff09; 5. 调…

基于SSM+Jsp的家用电器销售网站

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

微信小程序获取 OpenId 和 UnionId

文章目录 1.什么是 OpenId 和 UnionId&#xff1f;2.获取 OpenId 和 UnionId 的办法3.备注 前言&#xff1a;最近开发小程序&#xff0c;需要通过用户登录的唯一值存储数据&#xff0c;查看手册发现要使用的是 “OpenId” 和 “UnionId” 1.什么是 OpenId 和 UnionId&#xff1…

仓储系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;用户管理&#xff0c;试剂管理&#xff0c;安全管理&#xff0c;存储管理 用户账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;试剂管理&#xff0c;安全管…

快速搭建rtsp server(Ubuntu)

在现代视频监控和实时视频流媒体应用中&#xff0c;实时流协议&#xff08;RTSP&#xff09;服务器扮演着至关重要的角色。无论是家庭安防系统、企业级监控还是流媒体服务&#xff0c;RTSP服务器都能提供高效、稳定的解决方案。然而&#xff0c;对于许多初学者或开发者来说&…

机器学习--生成式模型和判别式模型的具体分析

文章目录 生成式模型和判别式模型的具体分析生成式模型定义工作原理优点缺点常见模型 判别式模型 总结生成式模型判别式模型 生成式模型和判别式模型的具体分析 生成式模型和判别式模型在机器学习中有着不同的目标、应用场景和性能特点。以下将详细分析它们的定义、工作原理、…

【qt】绘图

绘图 一.画家二.绘图事件三.坐标体系四.画笔1.setColor2.setWidth3.setStyle4.setCapStyle5.setJoinStyle6.给画家配置笔 五.画刷1.setColor2.setStyle3.给画家设置刷子 六.用到的类汇总1.QRect 矩形2.QPoint 点3.QImage 图片4.QPixmap 图片5.QLine 线6.QPainterPath 路径 七.开…

aabb c++

题目描述 查找形如"aabb"的四位完全平方数&#xff0c;也即前两位数字相同&#xff0c;后两位数字也相同。 输入 无 输出 若干行&#xff0c;每行一个符合条件的四位数&#xff08;从小到大&#xff09;。 分析&#xff1a; 完全平方数&#xff1a; &#xff…

中国蚁剑 安装教程 2024年5月

2024/5/11 中国蚁剑 安装教程 一、下载中国蚁剑的加载器和核心源码&#xff08;两个都要用到&#xff09; github官方下载地址&#xff1a;https://github.com/AntSwordProject/ 参考文档&#xff1a;antSword/README_CN.md at master AntSwordProject/antSword GitHub 核…

Golang-分离式加载器(传参)AES加密

目录 enc.go 生成: dec.go --执行dec.go...--上线 cs生成个c语言的shellcode. enc.go go run .\enc.go shellcode 生成: --key为公钥. --code为AES加密后的数据, ----此脚本每次运行key和code都会变化. package mainimport ("bytes""crypto/aes"&…

【数据结构与算法】使用数组实现栈:原理、步骤与应用

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​ 目录 一、引言 &#x1f384;栈&#xff08;Stack&#xff09;是什么&#xff1f; &#x1…