Spring发布-订阅模式:解耦与异步通信的高效实现

文章目录

  • 前言
  • 一、发布订阅模式的基本概念
  • 二、发布订阅模式的实现
    • 1、定义事件
    • 2、发布事件
    • 3、订阅事件
      • 3.1、ApplicationListener接口
      • 3.2、@EventListener注解
      • 3.3、事件源Object source的作用
  • 三、开发应用场景
    • 1、社交网络平台
    • 2、电商系统
    • 3、金融交易系统
  • 总结

前言

  Spring框架通过发布订阅模式为组件间通信提供了高效且松散耦合的解决方案,提升了系统的灵活性和扩展性。本文将探讨该模式的原理、实现、应用场景及其优势与挑战。

一、发布订阅模式的基本概念

  发布订阅模式,又称为观察者模式(Observer Pattern)的一种变体,是一种基于消息传递的设计模式。在这个模式中,主要涉及三个核心角色:发布者(Publisher)订阅者(Subscriber)消息代理(Message Broker)

  发布者是消息的产生者,它负责生成特定类型的消息并将其发送到消息代理。发布者不需要了解有哪些订阅者对其发布的消息感兴趣,它只专注于消息的生成和发布。

  订阅者则是对特定类型消息感兴趣的组件,它们向消息代理注册自己感兴趣的消息类型。当消息代理接收到发布者发送的符合订阅者兴趣的消息时,会将消息转发给对应的订阅者。订阅者可以根据接收到的消息进行相应的业务处理。

  消息代理是发布者和订阅者之间的中介,它负责接收发布者的消息,并根据订阅者的注册信息将消息分发给相应的订阅者。消息代理的存在使得发布者和订阅者之间实现了高度的解耦,它们不需要直接相互引用或通信,只需要与消息代理进行交互即可。

二、发布订阅模式的实现

  下面通过发布订阅模式实现一个示例:在用户注册成功后,系统自动发送邮件通知用户。

1、定义事件

  • 定义事件类,事件类通常继承自org.springframework.context.ApplicationEvent
  • 我们可以定义一个UserRegisteredEvent类来表示用户注册成功的事件
public class UserRegisteredEvent extends ApplicationEvent {// 这里的User是一个包含用户相关信息的实体类private User user;// source:事件的源对象,用于表明这个事件是由哪个对象触发的// 具体作用下面订阅事件中解释public UserRegisteredEvent(Object source, User user) {super(source);this.user = user;}public User getUser() {return user;}
}

2、发布事件

  • 发布事件的组件需要获取 ApplicationEventPublisher 实例,并通过它来发布事件
  • 在用户注册操作成功完成后,发布用户注册事件
@Service
public class UserRegistrationService {@Autowiredprivate ApplicationEventPublisher eventPublisher;public void registerUser(User user) {// 执行用户注册逻辑,如保存用户信息到数据库等// 注册成功后发布事件UserRegisteredEvent event = new UserRegisteredEvent(this, user);eventPublisher.publishEvent(event);}
}

3、订阅事件

3.1、ApplicationListener接口

  • 订阅者可以通过实现org.springframework.context.ApplicationListener接口来订阅特定的事件
  • 发送欢迎邮件的服务可以订阅UserRegisteredEvent事件
@Component
public class WelcomeEmailSender implements ApplicationListener<UserRegisteredEvent> {@Overridepublic void onApplicationEvent(UserRegisteredEvent event) {User user = event.getUser();// 发送欢迎邮件给用户的逻辑,如调用邮件发送接口等System.out.println("Sending welcome email to " + user.getEmail());}
}

3.2、@EventListener注解

  • 除了基于接口的订阅方式,Spring还提供了@EventListener注解来简化订阅者的实现
  • Spring还提供了对异步事件的支持,可以使用@Async注解来实现异步处理,从而避免阻塞事件的发布者
@Component
public class AnotherWelcomeEmailSender {@EventListener@Asyncpublic void handleUserRegisteredEvent(UserRegisteredEvent event) {User user = event.getUser();// 发送欢迎邮件的逻辑System.out.println("Another welcome email sent to " + user.getEmail());}
}

3.3、事件源Object source的作用

  假设有一个Web服务和一个API服务都可能触发UserRegisteredEvent事件,你可以在监听器中根据source进一步区分事件的处理方式

@EventListener
public void onUserRegistered(UserRegisteredEvent event) {Object source = event.getSource();if (source instanceof WebRegistrationService) {// 处理通过 Web 注册的用户} else if (source instanceof ApiRegistrationService) {// 处理通过 API 注册的用户}
}

三、开发应用场景

1、社交网络平台

  用户发布新动态后,动态发布服务触发创建事件。关注者列表服务订阅并推送该动态给关注者,推荐算法服务也订阅事件,分析内容为潜在用户推荐,扩大传播范围。

2、电商系统

  商品管理系统修改价格后发布价格变动事件,促销活动系统订阅并重新评估促销规则,购物车系统订阅并实时更新商品价格,确保用户看到最新价格。

3、金融交易系统

  用户交易时,交易处理服务发布交易事件,包含金额、类型等信息。账户余额更新系统订阅并更新余额及交易流水,确保准确性和可追溯性。风险监控系统也订阅事件,实时评估风险,检测异常交易并触发预警机制。

总结

  Spring的发布-订阅模式通过ApplicationEventApplicationListener@EventListener等组件,解耦了消息的生产者和消费者,并支持异步通信。这样可以让不同模块独立处理事件,提升系统的灵活性、可扩展性和响应速度。

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

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

相关文章

配置hive支持中文注释

hive元数据metastore默认的字符集是latin1&#xff0c;所以中文注释会乱码。但是不能将metastore库的字符集更改为utf-8&#xff0c;只能对特定表、特定列修改为utf-8。配置hive支持中文注释&#xff0c;主要在两个方面&#xff1a; 1、在Hive元数据存储的Mysql数据库中&#…

python实战案例笔记:统计出数据中路劲下没有文件的文件夹

数据样例&#xff1a;&#x1f447;有如下excel数据 需求&#xff1a;有如下excel&#xff0c;a.xls&#xff0c;统计出路劲下没有文件的路劲 详细实现代码&#xff1a; import os from openpyxl import Workbook from datetime import datetimedef get_empty_dirs(paths):# …

docker使用国内镜像

可用地址 https://docker.m.daocloud.io https://docker.rainbond.cc https://docker.1ms.run方法1:配置(需要重启docker) sudo vim /etc/docker/daemon.json # 在registry-mirrors中添加地址(没有的就直接创建了) #比如 {"registry-mirrors": ["https://dock…

机械臂的各种标定

文章目录 1. 工具坐标系标定2. 工具手标定3. 手眼标定联系 在工程中&#xff0c;同时使用工具坐标系标定、工具手标定和手眼标定的概念、目的和作用如下&#xff1a; 1. 工具坐标系标定 概念&#xff1a; 工具坐标系标定是指确定工具相对于机器人坐标系的位置和姿态关系的过程…

Oracle Managed Files(OMF)

Oracle Managed Files 是指&#xff1a; 在创建表空间文件等文件时&#xff0c;可以不必指定文件路径&#xff0c;由Oracle自动在某个目录下创建&#xff0c;文件名也是Oracle自动命名。 那这个OMF怎么使能呢&#xff1f; 其实是靠设置一些参数&#xff0c;指定要存储的目录…

GXUOJ-算法-第一次作业(整数划分、汉诺塔、排列问题、数塔问题)

1.整数划分 问题描述 GXUOJ | 整数划分 题解 #include<bits/stdc.h> using namespace std; const int N1010,mod1e97;int n; int f[N];int main(){cin>>n;f[0]1;for(int i1;i<n;i){for(int ji;j<n;j){f[j](f[j]f[j-i])%mod;}}cout<<f[n]; } 2.汉诺塔…

新服务器ubuntu系统相关操作

1、查看驱动:驱动版本535.216.01能够支持cuda12.2,下面直接使用默认安装的cuda。 2、赋予用户管理员权限。 首先有超级用户(root)权限来编辑 /etc/sudoers 文件,visudo 是一个命令,用于安全地编辑 /etc/sudoers 文件。运行: sudo visudo 在 visudo 编辑器中,找到类似…

【Linux命令】su、sudo、sudo su、sudo -i、sudo -l的用法和区别

su 命令 su (Switch User 切换用户)&#xff0c;允许用户切换到另一个用户的身份&#xff0c;默认情况下是切换到 root 用户。 默认行为&#xff1a;如果只运行 su&#xff0c;则系统会要求输入 root 用户的密码来切换到 root 用户&#xff0c;获取管理员权限。 切换到其他用…

docker-开源nocodb,使用已有数据库

使用已有数据库 创建本地数据库 数据库&#xff1a;nocodb 用户&#xff1a;nocodb 密码&#xff1a;xxxxxx修改docker-compose.yml 默认网关的 IP 地址是 172.17.0.1&#xff08;适用于 bridge 网络模式&#xff09;version: "2.1" services:nocodb:environment:…

near-synonym反义词生成(2):Prompt +Bert-MLM(FT)

near-synonym之反义词生成方法二 near-synonym, 中文反义词/近义词/同义词(antonym/synonym)工具包. 方法一为(neg_antonym): Word2vec -> ANN -> NLI -> Length 方法二为(mlm_antonym): Prompt Bert-MLM(FT) Beam-Search 项目地址 github: https://github.com/yon…

基于16QAM的载波同步和定时同步性能仿真,采用四倍采样,包括Costas环和gardner环

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 载波同步是…

用ttf文件解决python画图乱码和中文方框问题

#将字体放到某个路径下&#xff0c;下载的字体simsun支持中文 font FontProperties(fname“/usr/share/fonts/chinese/simsun.ttc”,size15) 我的字体文件在 “D:\中文字体TTF源文件\中文字体TTF源文件\simhei.ttf” 帮我解决乱码问题 import os import pandas as pd import…

谷云科技数据集成社区焕新登场:功能、资源、会员权益全面升级

12月26日&#xff0c;谷云科技ETLCloud技术社区迎来全新升级。升级后社区的内容更加丰富&#xff0c;满足社区用户更多需要。 功能更细致&#xff0c;查找更方便 社 区 问 答 | 博 客 文 章 | 文 档 中 心 作为社区内容贡献的核心板块&#xff0c;我们对社区问答、博客…

MySql详细教程-从入门到进阶(超实用)

基础篇 通用语法及分类 DDL: 数据定义语言&#xff0c;用来定义数据库对象&#xff08;数据库、表、字段&#xff09;DML: 数据操作语言&#xff0c;用来对数据库表中的数据进行增删改DQL: 数据查询语言&#xff0c;用来查询数据库中表的记录DCL: 数据控制语言&#xff0c;用…

20241225在ubuntu20.04.5下监控SSD

20241225在ubuntu20.04.5下监控SSD 2024/12/25 20:29 参考资料&#xff1a; 百度&#xff1a;ubuntu查看ssd寿命 方法 1&#xff1a;使用「磁盘」工具监测 SSD 健康状态 sudo apt install gnome-disk-utility 方法 2&#xff1a;使用 smartctl 工具检查 SSD 健康状态 Ubuntu 和…

node.js之---单线程异步非阻塞 I/O

单线程模型 1、Node.js 使用 单线程 来处理客户端请求和执行任务 2、如果遇到异步任务&#xff0c;node.js使用事件循环和异步 I/O 模型&#xff0c;使得它能够高效地处理大量并发请求 异步操作有哪些 1、读取文件 2、网络请求 3、数据库操作等等 异步非阻塞 I/O Node.…

基于PLC的电梯控制系统(论文+源码)

1.系统设计 电梯采用了PLC控制方式&#xff0c;通过对PLC进行逻辑程序设计&#xff0c;电梯不仅在控制水平上得到了质的提升&#xff0c;同时在安全性上也得到了大大提高。控制系统在构造上实现了简洁化&#xff0c;不仅优化了硬件接线方便了线路施工&#xff0c;同时对控制要…

【AR的手势识别算法有哪些】

在增强现实&#xff08;AR&#xff09;应用中&#xff0c;手势识别是实现用户与虚拟环境互动的关键技术之一。手势识别算法通过捕捉并分析用户的手势&#xff0c;转化为具体的控制命令&#xff0c;从而实现对虚拟物体、机器设备等的操作。以下是常见的AR手势识别算法及其实现方…

C++ hashtable

文章目录 1. 基本概念2. 哈希函数3. 哈希冲突及解决方法开放定址法链地址法再哈希法建立公共溢出区4. 哈希表的操作实现5. 内存管理及优化 时间复杂度理想情况&#xff08;无哈希冲突或冲突极少&#xff09;一般情况&#xff08;考虑哈希冲突及解决方法&#xff09;综合来看 以…

深度学习使用Anaconda打开Jupyter Notebook编码

新手入门深度学习使用Anaconda打开Jupyter Notebook编码 1. 安装Anaconda 第一种是Anaconda官网下载安装包&#xff0c;但是很慢&#xff0c;不太建议 第二种使用国内清华大学镜像源下载 选择适合自己电脑的版本&#xff0c;支持windows&#xff0c;linux系统 下载完之后自行…