当前位置: 首页 > news >正文

Spring源码分析之事件机制——观察者模式(三)

目录

自定义事件

事件监听器

事件发布者(服务层)

使用示例controller层


Spring源码分析之事件机制——观察者模式(一)-CSDN博客

Spring源码分析之事件机制——观察者模式(二)-CSDN博客

这两篇文章是这个篇章的前篇,感兴趣的读者可以阅读一下,从spring源码分析观察者模式

接下来说明一下Spring事件机制使用案例,就一个模拟用户注册场景的场景吧,事件机制其实还可以运用到更加广泛的作用。

说实话,个人感觉Spring事件机制真的好用。

自定义事件

public class UserRegisteredEvent extends ApplicationEvent {private final String username;private final String email;private final LocalDateTime registeredTime;public UserRegisteredEvent(Object source, String username, String email) {super(source);this.username = username;this.email = email;this.registeredTime = LocalDateTime.now();}// getter方法public String getUsername() {return username;}public String getEmail() {return email;}public LocalDateTime getRegisteredTime() {return registeredTime;}
}

事件监听器

@Component
@Order(1)  // 定义监听器执行顺序
public class EmailNotificationListener implements ApplicationListener<UserRegisteredEvent> {private final EmailService emailService;@Autowiredpublic EmailNotificationListener(EmailService emailService) {this.emailService = emailService;}@Overridepublic void onApplicationEvent(UserRegisteredEvent event) {// 发送欢迎邮件emailService.sendWelcomeEmail(event.getEmail(), event.getUsername());log.info("Welcome email sent to user: {}", event.getUsername());}
}
@Component
@Order(2)
public class UserCacheListener implements ApplicationListener<UserRegisteredEvent> {private final CacheManager cacheManager;@Autowiredpublic UserCacheListener(CacheManager cacheManager) {this.cacheManager = cacheManager;}@Overridepublic void onApplicationEvent(UserRegisteredEvent event) {// 更新用户缓存cacheManager.putUserCache(event.getUsername());log.info("User cache updated for: {}", event.getUsername());}
}

事件发布者(服务层)

@Service
@Transactional
public class UserService {private final UserRepository userRepository;private final ApplicationEventPublisher eventPublisher;@Autowiredpublic UserService(UserRepository userRepository, ApplicationEventPublisher eventPublisher) {this.userRepository = userRepository;this.eventPublisher = eventPublisher;}public User registerUser(String username, String email, String password) {// 验证用户数据validateUserData(username, email, password);// 创建用户User user = new User(username, email, password);user = userRepository.save(user);// 发布用户注册事件eventPublisher.publishEvent(new UserRegisteredEvent(this, username, email));log.info("User registered and event published: {}", username);return user;}private void validateUserData(String username, String email, String password) {// 数据验证逻辑}
}

使用示例controller层

@RestController
@RequestMapping("/api/users")
public class UserController {private final UserService userService;@Autowiredpublic UserController(UserService userService) {this.userService = userService;}@PostMapping("/register")public ResponseEntity<UserDTO> registerUser(@RequestBody UserRegistrationRequest request) {User user = userService.registerUser(request.getUsername(),request.getEmail(),request.getPassword());return ResponseEntity.ok(UserDTO.fromUser(user));}
}

用户注册时,UserService发布UserRegisteredEvent事件,EmailNotificationListener同步处理邮件发送,UserCacheListener同步更新缓存,AsyncAnalyticsListener异步处理统计数据,通过@Order注解控制监听器执行顺序。

这种实现方式将用户注册的核心逻辑与后续的处理操作解耦,使得系统更容易维护和扩展。每个监听器都专注于自己的职责,可以独立地添加、移除或修改,而不会影响其他部分的代码。

相关文章:

Spring源码分析之事件机制——观察者模式(三)

目录 自定义事件 事件监听器 事件发布者&#xff08;服务层&#xff09; 使用示例controller层 Spring源码分析之事件机制——观察者模式&#xff08;一&#xff09;-CSDN博客 Spring源码分析之事件机制——观察者模式&#xff08;二&#xff09;-CSDN博客 这两篇文章是这…...

C#实现画图,及实现图像运动,C#中GDI+图形图像技术(Graphics类、Pen类、Brush类)C#之快速入门GDI+绘图 C#实现快速画图功能

下载源码 <-------- 在C#的世界里&#xff0c;GDI如同一位多才多艺的艺术家&#xff0c;以其强大的绘图能力&#xff0c;让开发者能够轻松地在应用程序中挥洒创意&#xff0c;绘制出丰富多彩的图形世界。GDI不仅支持基本的几何图形绘制&#xff0c;还能处理复杂的图像处理任…...

【51单片机零基础-chapter6:LCD1602调试工具】

实验0-用显示屏LCD验证自己的猜想 如同c的cout,前端的console.log() #include <REGX52.H> #include <INTRINS.H> #include "LCD1602.h" int var0; void main() {LCD_Init();LCD_ShowNum(1,1,var211,5);while(1){;} }实验1-编写LCD1602液晶显示屏驱动函…...

算法题(24):只出现一次的数字(二)

审题&#xff1a; 数组中除了答案元素只出现一次外&#xff0c;其他元素都会出现三次&#xff0c;我们需要找到并返回答案元素 思路&#xff1a; 由于现在会出现三次&#xff0c;所以利用异或运算符的方法就会失效。而所有数据都在32位二进制范围内&#xff0c;所以我们采用依次…...

趣味编程:心形曲线

目录 1.序言 2.代码展示 3.代码详解 3.1 头文件包含 3.2 绘制坐标轴函数 3.3 main 函数主体部分 4. 小结 1.序言 2025年的第一篇博客就用这个笛卡尔心形图开篇吧&#xff0c;寓意着新年大家能够有心有所属&#xff0c;祝诸位程序猿 / 程序媛 能够早点遇到自己的另一半。…...

C# 设计模式(结构型模式):享元模式

C# 设计模式&#xff08;结构型模式&#xff09;&#xff1a;享元模式 (Flyweight Pattern) 在软件开发中&#xff0c;尤其是在处理大量对象时&#xff0c;我们常常会面临内存和性能上的挑战。当多个对象具有相似的状态时&#xff0c;通常会占用大量的内存资源&#xff0c;从而…...

计算机毕业设计Django+Tensorflow音乐推荐系统 音乐可视化 卷积神经网络CNN LSTM音乐情感分析 机器学习 深度学习 Flask

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

mysql 死锁案例及简略分析

准备数据 # 创一个测试表&#xff0c;存储引擎使用 innodb create table test_lock (id int primary key auto_increment,name varchar(20),age int )engine innodb;insert into test_lock (name,age) values (ionc001,10); insert into test_lock (name,age) values (ionc00…...

第四届计算机、人工智能与控制工程

第四届计算机、人工智能与控制工程 The 4th International Conference on Computer, Artificial Intelligence and Control Engineering 重要信息 大会官网&#xff1a;www.ic-caice.net 大会时间&#xff1a;2025年1月10-12日 大会地点&#xff1a;中国合肥 (安徽大学磬苑…...

RIP配置实验

RIP配置实验 案例简介 天一公司下属三个分公司&#xff0c;属于不同的地区&#xff0c;三个公司之间用路由器连接&#xff0c;路由器名称分别为分别为 Router0、Router1、Router2&#xff0c;请把一公司的部门pc0,通过二公司路由器&#xff0c;连接三公司的部门pc1,公司之间通…...

C# 整型、浮点型 数值范围原理分析

总目录 前言 一、整型、浮点型 数值范围列表 二、什么是大小、范围 在上面的列表中&#xff0c;每个数据类型都有自己的Range (范围) 和 Size (大小)。 1. 范围 范围好理解&#xff0c;就是对应数据类型的数据范围&#xff0c;如 sbtyte 的数据范围是 -128~127&#xff0c;超…...

Adobe Acrobat Pro DC 2023 下载安装教程,附详细图文

简介&#xff1a; Adobe Acrobat Pro DC 2023 是由 Adobe 公司推出的一款全面的 PDF 编辑、查看和管理软件。这款软件无论是个人用户还是企业级用户&#xff0c;都可以凭借其强大的功能满足不同的需求。作为一款业内领先的 PDF 处理工具&#xff0c;Adobe Acrobat Pro DC 不仅…...

stable diffusion秋叶启动器安装roop插件

方法简洁明了&#xff1a; 第一步&#xff1a;下载秋叶启动器 第二步&#xff1a;输入网址&#xff1a;https://visualstudio.microsoft.com/zh-hans/downloads/&#xff0c;下载vs安装程序&#xff0c;安装开始会自动弹出如下窗口&#xff0c;选择2个环境&#xff1a;Python开…...

7-14 统计工龄

给定公司多名员工的工龄&#xff0c;按输入工龄顺序输出每个工龄段有多少员工。 输入格式: 给出多个整数&#xff0c;即每个员工的工龄&#xff0c;范围在[0, 50]。 输出格式: 按输入工龄顺序输出每个工龄的员工个数&#xff0c;格式为&#xff1a;“工龄:人数”。 每项占一…...

OLED的显示

一、I2C I2C时序&#xff1a;时钟线SCL高电平下&#xff1a;SDA由高变低代表启动信号&#xff0c;开始发送数据&#xff1b;SCL高电平时&#xff0c;数据稳定&#xff0c;数据可以被读走&#xff0c;开始进行读操作&#xff0c;SCL低电平时&#xff0c;数据发生改变&#xff1…...

本地测试文件解析

PostMapping("/test") public void test() throws IOException {Path csvFile Paths.get("D:\\test/27.csv");//虚拟机退出时删除临时文件csvFile.toFile().deleteOnExit();List<String> list Files.readAllLines(csvFile, Charset.forName("…...

Elasticsearch JavaRestClient版

文章目录 初始化RestHighLeveClient&#xff08;必要条件&#xff09;索引库操作1.创建索引库&#xff08;4步&#xff09;2.删除索引库&#xff08;3步&#xff09;3.判断索引库是否存在&#xff08;3步&#xff09;4.总结&#xff1a;四步走 文档操作1.创建文档&#xff08;4…...

ubuntu 使用s3fs配置自动挂载对象存储

一、环境准备 1.有访问对象存储权限的AKSK 2.服务器、对象存储 二、实施步骤 sudo apt update sudo apt install s3fs echo "AK:SK" >/home/ubuntu/.passwd-s3fs ---位置自定义 chmod 600 /home/ubuntu/.passwd-s3fs ---权限必须要有 mkdir /data sudo s3fs …...

SQL字符串截取函数——Left()、Right()、Substring()用法详解

SQL字符串截取函数——Left&#xff08;&#xff09;、Right&#xff08;&#xff09;、Substring&#xff08;&#xff09;用法详解 1. LEFT() 函数&#xff1a;从字符串的左侧提取指定长度的子字符串。 LEFT(string, length)string&#xff1a;要操作的字符串。length&#x…...

关系分类(RC)模型和关系抽取(RE)模型的区别

目标不同 关系分类模型&#xff1a;对给定的实体对在给定句子中预测其关系类型。两阶段&#xff08;RC&#xff09; 关系抽取模型&#xff1a;从句子中识别出所有潜在实体对&#xff0c;并为其预测关系类型。一阶段&#xff08;NERRE&#xff09; 训练/预测阶段输入输出数据不…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...