在实际开发中,我们经常会遇到这样的场景: 一个核心业务完成后,需要触发多个后续操作,但又不希望代码彼此强耦合。
例如:用户注册完成 → 发送欢迎邮件、写审计日志、发放新人积分。
如果直接在一个方法里顺序调用,很快就会演变成难以维护的'上帝方法'。
Spring Boot 事件机制基于发布 - 订阅模式,通过 ApplicationEvent 实现业务解耦。核心角色包括事件发布者、监听器和事件本身。使用 publishEvent 发布事件,配合 ApplicationListener 接口或@EventListener 注解接收处理。支持异步执行避免阻塞主流程。适用于用户注册、订单完成等需要多模块后置处理的场景,符合单一职责原则,提升系统可维护性。

在实际开发中,我们经常会遇到这样的场景: 一个核心业务完成后,需要触发多个后续操作,但又不希望代码彼此强耦合。
例如:用户注册完成 → 发送欢迎邮件、写审计日志、发放新人积分。
如果直接在一个方法里顺序调用,很快就会演变成难以维护的'上帝方法'。
Spring 提供的事件机制(ApplicationEvent),正是为了解决这类问题而生。
public void registerUser(String username) {
saveUser(username);
sendWelcomeEmail(username);
addPoints(username);
writeLog(username);
}
这种写法存在明显问题:
事件机制的核心思想是 发布–订阅:
注册完成 ↓ 发布「用户注册事件」 ↓ 多个监听器各自处理自己的逻辑
Spring 事件机制本质是一个 发布 - 订阅模型(Publish–Subscribe)。
| 角色 | 说明 |
|---|---|
| Event | 事件本身,表示'发生了什么' |
| Publisher | 事件发布者 |
| Listener | 事件监听者 |
publishEvent() ↓ ApplicationContext(Spring 事件总线) ↓ 匹配事件类型 ↓ 调用对应的 Listener
只要事件类型匹配,监听器就会被自动调用。
下面通过一个 '用户注册事件' 的示例,完整演示 Spring 事件机制的使用。
import org.springframework.context.ApplicationEvent;
public class UserRegisteredEvent extends ApplicationEvent {
private final String username;
public UserRegisteredEvent(Object source, String username) {
super(source);
this.username = username;
}
public String getUsername() {
return username;
}
}
说明:
ApplicationEventimport 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 register(String username) {
System.out.println("✅ 用户注册成功:" + username);
// 发布事件
publisher.publishEvent(new UserRegisteredEvent(this, username));
}
}
关键点:
ApplicationEventPublisher 由 Spring 自动注入publishEvent() 只负责'发通知'import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class UserRegisteredListener implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
System.out.println("📩 监听到用户注册事件,发送欢迎消息:" + event.getUsername());
}
}
核心代码是这一行:
implements ApplicationListener<UserRegisteredEvent>
含义是:
当
UserRegisteredEvent被发布时,该监听器会自动执行
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DemoRunner {
@Bean
CommandLineRunner run(UserService userService) {
return args -> userService.register("alice");
}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
启动项目后,控制台输出如下:
说明:
@Component
public class LogListener implements ApplicationListener<UserRegisteredEvent> {}
@Component
public class PointListener implements ApplicationListener<UserRegisteredEvent> {}
👉 不修改注册逻辑即可扩展功能
@EventListener(更简洁)@EventListener
public void handle(UserRegisteredEvent event) {
System.out.println(event.getUsername());
}
@Async
@EventListener
public void handle(UserRegisteredEvent event) {}
并在启动类或配置类中开启异步:
@EnableAsync
✅ 适合场景
❌ 不适合场景
Spring 事件机制,本质上是一种轻量级的'服务内事件驱动架构'。
它非常适合用于:

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online