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

news2024/12/26 9:25:04

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> {
    @Override
    public 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 {
    @Resource
    private ApplicationContext applicationContext;


    @Override
    public 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.coloradmin.cn/o/1807726.html

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

相关文章

AI数据分析:根据Excel表格数据绘制柱形图

工作任务&#xff1a;将Excel文件中2013年至2019年间线上图书的销售额&#xff0c;以条形图的形式呈现&#xff0c;每个条形的高度代表相应年份的销售额&#xff0c;同时在每个条形上方标注具体的销售额数值 在deepseek中输入提示词&#xff1a; 你是一个Python编程专家&#…

OpenGauss数据库-4.表的创建、修改与删除

第1关&#xff1a;创建表 gsql -d postgres -U gaussdb -W passwd123123 create database testdb; \c testdb; passwd123123 create table test_table (test_id integer not null,test_info char(36)); 第2关&#xff1a;修改表 gsql -d testsb -U gaussdb -W passwd123123 …

Python实现删除Word文档中带有“指定内容”的段落文本(7)

前言 本文是该专栏的第7篇,后面会持续分享Python办公自动化干货知识,记得关注。 在处理word文档内容的时候,有时候我们需要一个干净整洁的文本内容。比如说,如下图所示的情况: 在处理上述word文档内容的时候,我们希望将文本底部的“下载链接”以及“附件信息”两个段落,…

Virustotal查询恶意进程

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

aabb c++

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

[图解]建模相关的基础知识-07

1 00:00:04,710 --> 00:00:08,900 这是划分&#xff0c;下一个是有序对的概念 2 00:00:11,720 --> 00:00:13,800 我们知道集合是不分顺序的 3 00:00:15,090 --> 00:00:18,200 我们花括号来代表集合的话 4 00:00:18,210 --> 00:00:21,000 AB花括号等于BA花括号 …

ORA-01652 表空间不够解决方案

前章&#xff1a;出现表空间不足不要手动强制删除对应数据文件存储目录下的DBF文件&#xff0c;需要用SQL语句进行数据文件的DROP&#xff0c;否则会导致ORA-01033报错&#xff0c;因为我没有开启数据库的归档所以不能通过RECOVER的形式找回数据文件最后只能重装本地ORACLE。 …

首途第三十三套清新简约卡片风格蓝紫渐变色短视频模板 | 苹果CMSV10主题

首途第三十三套清新简约卡片风格蓝紫渐变色短视频模板 | 苹果CMSV10主题 我们的简约风格&#xff0c;以纯洁的白色和深邃的紫色为主色调&#xff0c;为您提供了一种清新、时尚的浏览体验。在这个简洁而美丽的界面中&#xff0c;您可以轻松畅享各种精彩短视频。我们专注于简单的…

仓储系统的设计

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

vue29:普通组件的注册使用

<template><div class"App"><!-- 头部组件 --><HmHeader></HmHeader><!-- 主体组件 --><HmMain></HmMain><!-- 底部组件 --><HmFooter></HmFooter><!-- 如果 HmFooter tab 出不来 → 需要配置…

让AI做2024新高考1卷数学最后一题:AI智商横向对比!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

2013年 阿拉斯加巴罗活动层厚度和土壤含水量

Pre-ABoVE: Active Layer Thickness and Soil Water Content, Barrow, Alaska, 2013 ABoVE前&#xff1a;阿拉斯加巴罗活动层厚度和土壤含水量&#xff0c;2013年 简介 文件修订日期&#xff1a;2018-01-10 数据集版本&#xff1a;1 摘要 该数据集提供了 2013 年 8 月在…

泛微开发修炼之旅--13关于在Ecology中实现webservice接口对接异构系统时,出现无法调用接口的方案及源码

文章链接&#xff1a;泛微开发修炼之旅--13关于在Ecology中实现webservice接口对接异构系统时&#xff0c;出现无法调用接口的方案及源码

【数据结构】排序(上)

个人主页~ 堆排序看这篇~ 还有这篇~ 排序 一、排序的概念及应用1、概念2、常见的排序算法 二、常见排序的实现1、直接插入排序&#xff08;1&#xff09;基本思想&#xff08;2&#xff09;代码实现&#xff08;3&#xff09;时间复杂度&#xff08;4&#xff09;空间复杂度 2…

Java日期类Date、SimpleDateFormat 日期格式类、Calendar详细介绍

目录 一、Date类1.1 Date类简单介绍1.2 Date类的构造方法代码演示 二、SimpleDateFormat 日期格式化类2.1 SimpleDateFormat 日期格式化类简单介绍2.2 构造方法代码演示 日期格式化模板常用方法代码演示注意 三、Calendar类3.1 简单介绍3.2 创建对象代码演示 3.3 静态常量3.4 常…

Idea-Linux远程开发部署

第一步&#xff1a;File->Remote Development 第二步&#xff1a; 第三步&#xff1a; 第四步&#xff1a;在Host位置填写Linux虚拟机的IP地址&#xff0c;在Username、Password填写对应的账号密码后点击Test Connection测试连接。 第五步&#xff1a; 第六步&#xff1a;在…

iCloud完全指南:释放Apple云服务的终极潜力

iCloud是苹果公司提供的云服务&#xff0c;它允许用户存储和同步照片、文档、音乐、应用数据以及更多类型的文件。通过有效利用iCloud&#xff0c;用户可以在不同设备间无缝地访问和编辑内容。本文旨在全面介绍如何高效使用iCloud&#xff0c;确保您能够最大化这一服务的价值。…

【玩转C语言】第四讲--->操作符与循环语句

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 引言&#xff1a; 大家好&#xff0c;我是坊钰&#xff0c;为了让大家深入了解C语言&#xff0c;我开创了【玩转C语言系列】&#xff0c;将为大家介绍C语言相关知识…

C语言 | Leetcode C语言题解之第142题环形链表II

题目&#xff1a; 题解&#xff1a; struct ListNode* detectCycle(struct ListNode* head) {struct ListNode *slow head, *fast head;while (fast ! NULL) {slow slow->next;if (fast->next NULL) {return NULL;}fast fast->next->next;if (fast slow) {s…

vue2的form利用插槽修改错误提示UI

1. 需求 很多时候我们使用el-form想修改下错误提示的UI&#xff0c;比如table中使用form校验这类场景下错误提示的UI调整就非常重要。 2. 了解文档 Form-Item Scoped Slot name说明error自定义表单校验信息的显示方式&#xff0c;参数为 { error } 3.实际使用 html里使用…