Spring Event(事件驱动机制)

news2025/6/5 23:35:14

一、Spring Event 应用场景

1. 业务解耦
当一个业务操作触发多个后续动作时,用事件解耦各个动作,避免代码耦合。
比如:用户注册后同时发送欢迎邮件、积分赠送、日志记录等,这些逻辑可以通过事件发布+多个监听器异步处理。

2. 跨模块通信
不同模块间需要协同工作,但又不想直接调用彼此代码,事件机制能做到模块间松耦合通信。
比如订单模块发布“订单已支付”事件,库存模块监听此事件减少库存。

3. 异步处理
有些业务处理耗时且对用户响应速度影响较大,通过事件异步处理能提升性能和体验。

比如发短信、写日志、推送通知等。

4. 日志和审计
对系统行为做统一日志或审计,利用事件捕获业务操作,方便统一管理和扩展。

5. 系统监控和报警
关键事件触发时发送告警通知或写监控日志。

6. 分布式系统的领域事件
在微服务架构中,服务间通过领域事件(Domain Event)进行通信,保持服务间的解耦和业务一致性。

简单总结
Spring Event 适用于“一个动作触发多个后续独立操作”,尤其需要解耦、扩展和异步时。

二、简单使用 (同步)

1. 定义事件类

import org.springframework.context.ApplicationEvent;

public class UserRegisterEvent extends ApplicationEvent {
    private final String username;

    public UserRegisterEvent(Object source, String username) {
        super(source);
        this.username = username;
    }

    public String getUsername() {
        return username;
    }
}

2. 发布事件的组件(发布者)

import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    private final ApplicationEventPublisher publisher;

    public UserService(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void registerUser(String username) {
        System.out.println("注册用户:" + username);
        // 注册逻辑...

        // 发布事件
        publisher.publishEvent(new UserRegisterEvent(this, username));
    }
}

3. 监听事件的组件(监听者)

import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class EmailListener {

    @EventListener
    public void handleUserRegister(UserRegisterEvent event) {
        System.out.println("给用户发送欢迎邮件:" + event.getUsername());
        // 发送邮件逻辑...
    }
}

4. 测试调用

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class EventDemoApplication implements CommandLineRunner {

    private final UserService userService;

    public EventDemoApplication(UserService userService) {
        this.userService = userService;
    }

    public static void main(String[] args) {
        SpringApplication.run(EventDemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        userService.registerUser("张三");
    }
}

运行结果

注册用户:张三
给用户发送欢迎邮件:张三

三、简单使用 (异步)

如果你想加异步处理,只需要给监听方法加上 @Async 并开启异步支持即可:

@EnableAsync
@Component
public class EmailListener {

    @Async   // 加上此注解
    @EventListener
    public void handleUserRegister(UserRegisterEvent event) {
        // 异步发送邮件
    }
}

@Async 生效前提是你的 Spring 配置里必须加上 @EnableAsync 注解,否则 @Async 会被忽略,方法还是同步执行。

🧠 问题核心:
Spring 的异步事件监听(带 @Async 的 @EventListener) 本质上是通过线程池异步执行监听方法。它的执行成功或失败不会影响主业务流程,但也不会自动重试!

异步监听器(@Async)的执行顺序 无法通过 @Order 控制
@Order 只控制监听器在 同一个线程同步执行时 的顺序。
一旦加了 @Async,监听方法会被放到线程池里并发执行,顺序完全不确定。
你看到先发邮件后发短信,其实是线程调度的结果,不是按 @Order 顺序执行。

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

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

相关文章

生产环境MYSQL常见锁表场景

前言 锁表是我们在生产环境十分常见的问题之一,解决问题前需要先了解锁表产生的原因以找到解决方案,并制定方案以预防锁表,本文接下来会分别模拟元数据锁表(MDL锁)、行锁升级为表锁、死锁、**显示锁表 **四种锁表情形…

结构性设计模式之Composite(组合)

结构性设计模式之Composite(组合) 摘要: Composite(组合)模式通过树形结构表示"部分-整体"层次关系,使得用户能够统一处理单个对象和组合对象。该模式包含Component(组件接口&#x…

Java面试八股--04-MySQL

致谢:感谢整理!2025年 Java 面试八股文(20w字)_java面试八股文-CSDN博客 目录 1、Select语句完整的执行顺序 2、MySQL事务 3、MyISAM和InnoDB的区别 4、悲观锁和乐观锁怎么实现 5、聚簇索引与非聚簇索引区别 6、什么情况下my…

设计模式——访问者设计模式(行为型)

摘要 访问者设计模式是一种行为型设计模式,它将数据结构与作用于结构上的操作解耦,允许在不修改数据结构的前提下增加新的操作行为。该模式包含关键角色如元素接口、具体元素类、访问者接口和具体访问者类。通过访问者模式,可以在不改变对象…

实验设计与分析(第6版,Montgomery著,傅珏生译) 第10章拟合回归模型10.9节思考题10.1 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第10章拟合回归模型10.9节思考题10.1 R语言解题。主要涉及线性回归、回归的显著性、回归系数的置信区间。 vial <- seq(1, 10, 1) Viscosity <- c(160,171,175,182,184,181,188,19…

LeetCode 高频 SQL 50 题(基础版) 之 【高级查询和连接】· 下

上部分链接&#xff1a;LeetCode 高频 SQL 50 题&#xff08;基础版&#xff09; 之 【高级查询和连接】 上 题目&#xff1a;1164. 指定日期的产品价格 题解&#xff1a; select product_id,10 price from Products group by product_id having min(change_date) > 201…

机器学习——SVM

1.什么是SVM 支持向量机&#xff08;support vector machines&#xff0c;SVM&#xff09;是一种二分类模型&#xff0c;它将实例的特征向量映射为空间中的一些点&#xff0c;SVM 的目的就是想要画出一条线&#xff0c;以 “最好地” 区分这两类点&#xff0c;以至如果以后有了…

【音视频】FFmpeg 硬件(NVDIA)编码H264

FFmpeg 与x264的关系 ffmpeg软编码是使⽤x264开源项⽬&#xff0c;也就是说ffmpeg软编码H264最终是调⽤了x264开源项⽬&#xff0c;所以我们要先理解ffmpeg和x264的调⽤关系&#xff0c;这⾥我们主要关注x264_init。对于x264的参数都在 ffmpeg\libavcodec \libx264.c x264\co…

贪心算法应用:超图匹配问题详解

贪心算法应用&#xff1a;超图匹配问题详解 贪心算法在超图匹配问题中有着广泛的应用。下面我将从基础概念到具体实现&#xff0c;全面详细地讲解超图匹配问题及其贪心算法解决方案。 一、超图匹配问题基础 1. 超图基本概念 **超图&#xff08;Hypergraph&#xff09;**是普…

【Web应用】若依框架:基础篇13 源码阅读-前端代码分析

文章目录 ⭐前言⭐一、课程讲解过程⭐二、自己动手实操⭐总结 标题详情作者JosieBook头衔CSDN博客专家资格、阿里云社区专家博主、软件设计工程师博客内容开源、框架、软件工程、全栈&#xff08;,NET/Java/Python/C&#xff09;、数据库、操作系统、大数据、人工智能、工控、网…

[java八股文][JavaSpring面试篇]SpringCloud

了解SpringCloud吗&#xff0c;说一下他和SpringBoot的区别 Spring Boot是用于构建单个Spring应用的框架&#xff0c;而Spring Cloud则是用于构建分布式系统中的微服务架构的工具&#xff0c;Spring Cloud提供了服务注册与发现、负载均衡、断路器、网关等功能。 两者可以结合…

基于分布式状态机的集装箱智能道口软件架构方法

集装箱码头对进出场道口的通过能力始终是要求最高的&#xff0c;衡量道口的直接指标为道口通行效率&#xff0c;道口通行效率直接体现了集装箱码头的作业效率以及对外服务水平&#xff0c;进而直接影响到码头的综合能力。所以&#xff0c;码头普遍使用智能道口实现24小时无人值…

Vue 树状结构控件

1、效果图如下所示&#xff1a; 2、网络请求的数据结构如下&#xff1a; 3、新建插件文件&#xff1a;menu-tree.vue&#xff0c;插件代码如下&#xff1a; <template><div class"root"><div class"parent" click"onParentClick(pare…

【LUT技术专题】图像自适应3DLUT代码讲解

本文是对图像自适应3DLUT技术的代码解读&#xff0c;原文解读请看图像自适应3DLUT文章讲解 1、原文概要 结合3D LUT和CNN&#xff0c;使用成对和非成对的数据集进行训练&#xff0c;训练后能够完成自动的图像增强&#xff0c;同时还可以做到极低的资源消耗。下图为整个模型的…

vscode使用“EIDE”和“Cortex-Debug”插件利用st-link插件实现程序烧写以及调试工作

第一步&#xff1a;安装vscode插件“EIDE”EIDE和“Cortex-Debug”。 第二步&#xff1a;配置EIDE 2.1安装“实用工具”&#xff1a; 2.2 EIDE插件配置&#xff1a;根据安装的keil C51 keil MDK IAR的相关路径设置 第三步&#xff1a;配置Cortex-Debug插件 点击settings.jso…

Spring @Value注解的依赖注入实现原理

Spring Value注解的依赖注入实现原理 一&#xff0c;什么是Value注解的依赖注入二&#xff0c;实现原理三&#xff0c;代码实现1. 定义 Value 注解2. 实现 InstantiationAwareBeanPostProcessor3. 实现 AutowiredAnnotationBeanPostProcessor4. 占位符解析逻辑5. 定义 StringVa…

三、kafka消费的全流程

五、多线程安全问题 1、多线程安全的定义 使用多线程访问一个资源&#xff0c;这个资源始终都能表现出正确的行为。 不被运行的环境影响、多线程可以交替访问、不需要任何额外的同步和协同。 2、Java实现多线程安全生产者 这里只是模拟多线程环境下使用生产者发送消息&…

Axure形状类组件图标库(共8套)

点击下载《月下倚楼图标库(形状组件)》 原型效果&#xff1a;https://axhub.im/ax9/02043f78e1b4386f/#g1 摘要 本图标库集锦精心汇集了8套专为Axure设计的形状类图标资源&#xff0c;旨在为产品经理、UI/UX设计师以及开发人员提供丰富多样的设计素材&#xff0c;提升原型设计…

20250530-C#知识:String与StringBuilder

String与StringBuilder string字符串在开发中经常被用到&#xff0c;不过在需要频繁对字符串进行增加和删除时&#xff0c;使用StringBuilder有利于提升效率。 1、String string是一种引用类型而非值类型&#xff08;某些方面像值类型&#xff09;使用“”进行两个string对象的…

从 Docker 到 Containerd:Kubernetes 容器运行时迁移实战指南

一、背景 Kubernetes 自 v1.24 起移除了 dockershim&#xff0c;不再原生支持 Docker Engine&#xff0c;用户需迁移至受支持的 CRI 兼容运行时&#xff0c;如&#xff1a; Containerd&#xff08;推荐&#xff0c;高性能、轻量级&#xff09; CRI-O&#xff08;专为 Kuberne…