🍃🍃🍃Spring 事件机制:@EventListener用法

43 阅读2分钟

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


🧩 事件是什么?一句话

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

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

这就是解耦。 也是优雅。


👫 场景类比(超级好记)

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

Spring 就是按照这个来的。


🎭 主角三件套

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

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

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

public class UserRegisteredEvent {
    private final Long userId;
    public UserRegisteredEvent(Long userId) { this.userId = userId; }
    public Long getUserId() { return userId; }
}

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

@Component
public class UserService {
    @Autowired
    private ApplicationEventPublisher publisher;

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

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

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

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

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


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

Spring Boot 启动成功自动发布 ApplicationReadyEvent

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

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


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

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

想异步?两个操作:

① 开启异步

@EnableAsync
@Configuration
public class AsyncConfig {}

② 监听器上加 @Async

@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 -- main
📩(异步) 准备发邮件... event-async-1
✅ 邮件发送完成!

主线程不被阻塞。


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

@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;
    }
}
@Async("eventExecutor")
@EventListener
public void onUserRegistered(UserRegisteredEvent e) {...}

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

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