读完本文,你能做到:敢用、会用、讲得明明白白。
语速不快,信息全到。笑点有,废话无。


🧩 事件是什么?一句话

事件 = 我说一句,你听到了你再做事。

👉 发布事件的人 不关心 谁来处理。
👉 处理事件的人 不耦合 谁发的。

这就是解耦。 也是优雅。


👫 场景类比(超级好记)

  • 你喊:“开饭啦!”(事件)
  • 你妈、你爸、你弟 都可能来吃(监听器)
  • 你不管谁来,也不关心来不来。

Spring 就是按照这个来的。


🎭 主角三件套

名称 干啥的 类比
自定义事件 你要说的话 开饭啦!
ApplicationEventPublisher 扩音器 帮你喊出去
@EventListener 谁听到了谁行动 各自来吃饭

🎯 示例(最小可运行示例)

① 定义事件(随便一个类即可)

1
2
3
4
5
public class UserRegisteredEvent {
private final Long userId;
public UserRegisteredEvent(Long userId) { this.userId = userId; }
public Long getUserId() { return userId; }
}

② 发布事件(谁触发谁发布)

1
2
3
4
5
6
7
8
9
10
@Component
public class UserService {
@Autowired
private ApplicationEventPublisher publisher;

public void register(Long id) {
System.out.println("✅ 用户注册成功: " + id);
publisher.publishEvent(new UserRegisteredEvent(id));
}
}

谁需要让别人知道,就谁发事件。

③ 监听事件(谁关心谁就监听)

1
2
3
4
5
6
7
@Component
public class WelcomeMailListener {
@EventListener
public void onUserRegistered(UserRegisteredEvent e) {
System.out.println("📩 欢迎邮件已发送给用户: " + e.getUserId());
}
}

监听的关键点是参数类型决定了监听哪个事件。


🚀 启动后执行一次(内置事件)

Spring Boot 启动成功自动发布 ApplicationReadyEvent

1
2
3
4
5
6
7
@Component
public class AppStarted {
@EventListener
public void onReady(ApplicationReadyEvent e) {
System.out.println("🎉 服务已就绪,开始搬砖!");
}
}

📌 这个不用你发事件。Spring 会自动发。


⚡ 让监听异步执行(不堵主线程)

默认事件监听是同步的(你不说,我也不忍)。

想异步?两个操作:

① 开启异步

1
2
3
@EnableAsync
@Configuration
public class AsyncConfig {}

② 监听器上加 @Async

1
2
3
4
5
6
7
8
9
10
11
@Component
public class WelcomeMailListener {

@Async
@EventListener
public void onUserRegistered(UserRegisteredEvent e) {
System.out.println("📩(异步) 准备发邮件... " + Thread.currentThread().getName());
try { Thread.sleep(2000); } catch (Exception ignored) {}
System.out.println("✅ 邮件发送完成!");
}
}

输出示例:

1
2
3
✅ 用户注册成功: 1 -- main
📩(异步) 准备发邮件... event-async-1
✅ 邮件发送完成!

主线程不被阻塞。


🧵 自定义线程池(生产建议)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@EnableAsync
@Configuration
public class AsyncPoolConfig {
@Bean("eventExecutor")
public Executor pool() {
ThreadPoolTaskExecutor exec = new ThreadPoolTaskExecutor();
exec.setCorePoolSize(4);
exec.setMaxPoolSize(8);
exec.setQueueCapacity(200);
exec.setThreadNamePrefix("evt-");
exec.initialize();
return exec;
}
}
1
2
3
@Async("eventExecutor")
@EventListener
public void onUserRegistered(UserRegisteredEvent e) {...}

🧠 一句话总复盘(建议截图)

事件 = 解耦。
谁触发,谁发布;谁关心,谁监听。
启动就绪事件 Spring 自己发。
加 @Async 就能飞,配线程池才能稳。