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

Java Spring 事件驱动机制

文章目录

  • Java Spring 事件驱动机制详解:ApplicationEventPublisher 与 ApplicationEventPublisherAware
    • 一、什么是 Spring 的事件机制?
    • 二、`ApplicationEventPublisher` 接口
      • 示例:使用 `ApplicationEventPublisher` 发布事件
    • 三、`ApplicationEventPublisherAware` 接口
    • 四、自定义事件类
    • 五、事件监听器的两种写法
      • 1. 实现 `ApplicationListener` 接口
      • 2. 使用 `@EventListener` 注解(推荐)
    • 六、实战演示
    • 七、使用场景总结
    • 八、使用场景
    • 九、直接调用、spring事件机制、MQ
      • 1. **直接调用**
      • 2. **Spring事件机制**
      • 3. **MQ 消息队列方式(推荐用于服务间通信)**
    • ✅ 结论建议
    • 🔍 补充提示


Java Spring 事件驱动机制详解:ApplicationEventPublisher 与 ApplicationEventPublisherAware

一、什么是 Spring 的事件机制?

Spring 的事件机制是一种发布-订阅(Publish-Subscribe)模式的实现。它允许 Spring 容器中的 Bean 之间进行异步/同步通信,适合实现模块解耦、通知机制等场景。

事件驱动模型主要由三部分组成:

  • 事件(Event):继承自 ApplicationEvent 的自定义事件类
  • 事件发布者(Publisher):使用 ApplicationEventPublisher 发布事件
  • 事件监听器(Listener):通过实现 ApplicationListener 或使用 @EventListener 注解来接收事件

二、ApplicationEventPublisher 接口

ApplicationEventPublisher 是 Spring 的事件发布接口,提供如下方法:

void publishEvent(Object event);

当调用此方法时,Spring 会将事件广播给所有监听该类型事件的监听器。

示例:使用 ApplicationEventPublisher 发布事件

通过publishEvent方法,发布一个自定义事件类。MyCustomEvent就是自定义事件类

import com.wzw.entity.UserEvent;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;@Component
@RequiredArgsConstructor
public class EventPublisher {private final ApplicationEventPublisher publisher;public void publish(String message) {publisher.publishEvent(new UserEvent(this, message));}
}

三、ApplicationEventPublisherAware 接口

如果不想使用构造函数或字段注入的方式获取 ApplicationEventPublisher,可以实现 ApplicationEventPublisherAware 接口,Spring 会自动注入该依赖:

import com.wzw.entity.UserEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;@Component
public class EventPublisher implements ApplicationEventPublisherAware {private ApplicationEventPublisher publisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.publisher = applicationEventPublisher;}public void publish(String message) {publisher.publishEvent(new UserEvent(this, message));}
}

四、自定义事件类

可以创建一个继承自 ApplicationEvent 的事件类,也可以直接使用 POJO:

import org.springframework.context.ApplicationEvent;public class UserEvent extends ApplicationEvent {private String name;public UserEvent(Object source, String name) {super(source);this.name = name;}public String getName() {return name;}}

五、事件监听器的两种写法

1. 实现 ApplicationListener 接口

import com.wzw.entity.UserEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;@Component
public class EventListener implements ApplicationListener<UserEvent> {@Overridepublic void onApplicationEvent(UserEvent event) {System.out.println("-----实现接口ApplicationListener的监听方法:"+event.getName());}
}

2. 使用 @EventListener 注解(推荐)

import com.wzw.entity.UserEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;@Component
public class AnnoEventListener {@EventListenerpublic void handleEvent(UserEvent event) {System.out.println("注解监听器收到事件:" + event.getName());}
}

六、实战演示

测试方法

import com.wzw.Main;
import com.wzw.service.EventPublisher;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest(classes = Main.class)
public class PublisherTest {@Resourceprivate EventPublisher publisher;@Testpublic void test() {publisher.publish("张三");}
}

在这里插入图片描述

七、使用场景总结

使用场景推荐方式
解耦不同模块的业务逻辑使用事件发布机制
想要自动注入发布器使用构造函数注入 ApplicationEventPublisher
需要获取发布器但不想注入实现 ApplicationEventPublisherAware
接收事件通知实现监听器或使用 @EventListener

八、使用场景

Spring 的事件驱动机制是一个优雅的模块解耦方案。可以看做一个简单的MQ,常见用于:

  • 用户注册完成后发送欢迎邮件
  • 操作日志记录
  • 第三方系统通知(如消息推送、钉钉机器人)
  • 领域事件驱动设计(DDD)

九、直接调用、spring事件机制、MQ

特性直接方法调用Spring事件机制消息队列(MQ)
解耦性❌ 紧耦合(调用者必须知道被调用者)✅ 逻辑解耦(发布-监听)✅ 系统解耦(服务间完全独立)
通信范围进程内(方法内部)应用内(单个 Spring 容器)跨服务/跨系统
异步支持❌ 默认同步✅ 支持(结合 @Async✅ 天生支持异步
容错能力❌ 方法出错调用方也失败✅ 可控制监听异常行为✅ 高容错(重试/积压/确认机制)
消息持久化❌ 无❌ 无✅ 有(如 RabbitMQ、Kafka)
性能✅ 极快(本地内存)⚠️ 中等(有事件分发开销)⚠️ 较慢(涉及网络、序列化)
运维成本✅ 零✅ 极低❌ 高(部署、监控、保障消息可靠)
应用场景模块间简单调用应用内模块解耦、观察者模式服务间异步通信、削峰、广播、事务最终一致性
顺序保障✅ 同步调用按顺序执行⚠️ 依赖监听器线程实现⚠️ 依赖 MQ 实现(如 Kafka 分区)

✅ 举例对比:用户注册场景

场景:用户注册成功后,需完成以下动作:

  • 发送欢迎邮件
  • 写入操作日志
  • 向 CRM 系统推送用户数据

1. 直接调用

userService.register(user);
mailService.sendWelcome(user);
logService.writeLog(user);
crmService.pushUser(user);

✅ 简单
❌ 强耦合,crmService 出错可能影响主流程


2. Spring事件机制

userService.register(user);
eventPublisher.publishEvent(new UserRegisteredEvent(user));

然后由多个监听器来处理:

@EventListener
public void sendWelcomeEmail(UserRegisteredEvent event) { ... }@EventListener
public void writeLog(UserRegisteredEvent event) { ... }@EventListener
public void pushToCRM(UserRegisteredEvent event) { ... }

✅ 业务解耦
⚠️ 仍在同一个进程内,CRM 如果慢,仍可能拖慢主线程(除非加 @Async


3. MQ 消息队列方式(推荐用于服务间通信)

userService.register(user);
mqProducer.send("user.registered", user);
  • 邮件服务、日志服务、CRM 服务分别订阅 user.registered 主题并异步处理
  • 可持久化、失败重试、异步处理

✅ 系统间彻底解耦
✅ 网络分布式通信
⚠️ 成本高,需要部署 MQ 中间件(如 Kafka、RabbitMQ、RocketMQ)


✅ 结论建议

使用场景建议方案
简单的同步调用直接调用
应用内的解耦、逻辑分发(中小项目)Spring 事件机制
微服务之间、异步通信、可靠投递需求消息队列(Kafka、RabbitMQ 等)

🔍 补充提示

使用方式可靠性保障扩展性异常处理
直接调用全依赖代码主方法失败,整体失败
Spring事件局部 try-catch 或 @Async + @TransactionalEventListener某监听失败不影响主流程(可控制)
MQ支持 ACK、重试、死信队列可做到“最终一致性”

http://www.xdnf.cn/news/435277.html

相关文章:

  • 中医诊所药房开处方调剂库存管理h5/pc开源版开发
  • 提供全球86国/地区进出口税费,46国/地区监管条件,53国/地区税费计算
  • 第二十三天打卡
  • 项目管理系统流程:高效运作的关键所在
  • 使用ADB命令操作Android的apk/aab包
  • [SAP] 通过程序名获取事务码TCode
  • Python实例题:Pvthon实现简单的Web服务器
  • AI 编程新时代!字节 Seed-Coder 重磅登场
  • 第六章QT基础: Lambda表达式补充
  • [250513] “End of 10” 活动:应对 Windows 10 支持终止,推广 Linux 转型
  • livenessProbe 和 readinessProbe 最佳实践
  • Pytorch学习笔记(二十二)Audio - Audio I/O
  • 论文《Collaboration-Aware Graph Convolutional Network for Recommender Systems》阅读
  • 打卡DAY24
  • 【调度算法】LaCAM快速多智能体路径搜索算法
  • LLM大模型transform架构的核心知识
  • 《从协议层面剖析 VoIP 通信:SIP 信令流中的 RPort、注册与呼叫建立机制》
  • 20250512期:基于arcpy数据驱动的大批量规范化出图
  • 油桃缺陷检测数据集VOC+YOLO格式559张2类别
  • AI助力:零基础开启编程之旅
  • 【JavaScript】原生 JavaScript 实现 localStorage 过期时间
  • Linux常用命令39——free显示系统内存使用量情况
  • 软件测试——面试八股文(入门篇)
  • 项目三 - 任务6:回文日期判断
  • 飞拍技术介绍
  • 从数据中台到数据飞轮:数字化转型的演进之路
  • Google Earth Engine(GEE) 代码详解:批量计算_年 NDVI 并导出(附 Landsat 8 数据处理全流程)
  • 这类物种组织heatmap有点东西
  • MySQL初阶:查询进阶
  • 京东平台商品评论接口接入指南与代码实现