当前位置: 首页 > 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、重试、死信队列可做到“最终一致性”

相关文章:

  • KT148A语音芯片发码很难播放_将4脚对地一下再发正常,什么原因?
  • git Authentication failed for 的解决办法
  • vim,gcc/g++,makefile,cmake
  • 适应性神经树:当深度学习遇上决策树的“生长法则”
  • VSCode中Node.js 使用教程
  • 深度学习计算
  • IP代理池环境配置
  • React面试常问问题详解
  • 《ffplay 读线程与解码线程分析:从初始化到 seek 操作,对比视频与音频解码的差异》
  • ElasticSearch父子关系数据建模
  • 多线程代码案例-1 单例模式
  • 基于深度学习的水果识别系统设计
  • 无人机避障——(运动规划部分)深蓝学院动力学kinodynamic A* 3D算法理论解读(附C++代码)
  • Qt 样式表qss学习
  • 【Qt】之音视频编程2:QtAV的使用篇
  • Kubernetes容器运行时:Containerd vs Docker
  • 奇妙小博客
  • 项目里程碑未被明确,如何有效控制进度
  • Java Solon v3.3.0 发布(国产优秀应用开发基座)
  • 操作实例 :使用rpm命令安装并解压RAR文档的工具软件UNRAR
  • 袁思达已任中国科学院办公厅主任
  • 国务院关税税则委员会公布公告调整对原产于美国的进口商品加征关税措施
  • 专访|茸主:杀回UFC,只为给自己一个交代
  • 习近平同巴西总统卢拉会谈
  • 兰州大学教授安成邦加盟复旦大学中国历史地理研究所
  • 香港根据《维护国家安全条例》订立附属法例