Spring Boot Event 观察者模式,轻松带你实现业务解耦

Spring Boot Event 观察者模式,轻松带你实现业务解耦
最新回答
苏仙小可爱

2020-06-12 02:35:00

Spring Boot Event 是基于 Spring Framework 的事件发布-监听机制,本质是观察者模式的实现,用于解耦业务逻辑,尤其适合处理异步任务(如邮件、短信发送)或跨模块通知场景。以下是核心实现步骤与异步配置说明:

一、同步事件实现

同步事件适用于需要立即响应的场景,事件发布后监听器会同步执行。

1. 自定义事件

继承 ApplicationEvent 类,定义事件对象并传递业务数据。

public class CustomEvent extends ApplicationEvent { private String message; public CustomEvent(Object source, String message) { super(source); this.message = message; } public String getMessage() { return message; }}

2. 定义监听器
  • 方式1:实现 ApplicationListener 接口,重写 onApplicationEvent 方法。
@Componentpublic class CustomListener implements ApplicationListener<CustomEvent> { @Override public void onApplicationEvent(CustomEvent event) { System.out.println("同步监听: " + event.getMessage()); }}
  • 方式2:使用 @EventListener 注解(推荐,更简洁)。
@Componentpublic class AnnotationListener { @EventListener public void handleEvent(CustomEvent event) { System.out.println("注解监听: " + event.getMessage()); }}

3. 定义发布者

通过 ApplicationEventPublisher 发布事件,通常由 Spring 容器注入。

@Servicepublic class EventPublisherService { @Autowired private ApplicationEventPublisher publisher; public void publishEvent(String message) { System.out.println("发布事件前"); publisher.publishEvent(new CustomEvent(this, message)); System.out.println("发布事件后"); }}

4. 测试同步事件

调用发布者方法,观察控制台输出顺序:

@SpringBootTestpublic class EventTest { @Autowired private EventPublisherService publisher; @Test public void testSyncEvent() { publisher.publishEvent("Hello, Spring Event!"); }}

输出结果

发布事件前同步监听: Hello, Spring Event!注解监听: Hello, Spring Event!发布事件后

二、异步事件实现

异步事件适用于非实时性任务(如发送短信),避免阻塞主线程。

1. 自定义异步事件

与同步事件定义相同,无需额外配置。

public class AsyncEvent extends ApplicationEvent { private String content; public AsyncEvent(Object source, String content) { super(source); this.content = content; } public String getContent() { return content; }}

2. 定义异步监听器

使用 @Async 注解标记异步方法,并配合 @EventListener 监听事件。

@Componentpublic class AsyncListener { @Async @EventListener public void handleAsyncEvent(AsyncEvent event) { try { Thread.sleep(2000); // 模拟耗时操作 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步监听线程: " + Thread.currentThread().getName() + ", 内容: " + event.getContent()); }}

3. 定义发布者

与同步发布者一致,无需修改。

@Servicepublic class AsyncPublisherService { @Autowired private ApplicationEventPublisher publisher; public void publishAsyncEvent(String content) { System.out.println("发布异步事件前"); publisher.publishEvent(new AsyncEvent(this, content)); System.out.println("发布异步事件后"); }}

4. 开启异步支持
  • 启动类添加 @EnableAsync 注解。
@SpringBootApplication@EnableAsyncpublic class EventApplication { public static void main(String[] args) { SpringApplication.run(EventApplication.class, args); }}

5. 测试异步事件

调用异步发布者方法,观察线程名与执行顺序:

@SpringBootTestpublic class AsyncEventTest { @Autowired private AsyncPublisherService asyncPublisher; @Test public void testAsyncEvent() { asyncPublisher.publishAsyncEvent("Async Message"); }}

输出结果

发布异步事件前发布异步事件后异步监听线程: task-1, 内容: Async Message
  • 主线程(测试方法)快速结束,不等待异步任务。
  • 异步任务由线程池(默认 SimpleAsyncTaskExecutor)执行,线程名为 task-X。
三、关键注意事项
  1. 线程池配置:默认使用 SimpleAsyncTaskExecutor(每次创建新线程),生产环境建议自定义线程池(如 ThreadPoolTaskExecutor)。
  2. 异常处理:异步方法中的异常需手动捕获,否则会静默失败。
  3. 事件顺序:同步监听器按注册顺序执行,异步监听器无顺序保证。
  4. 事务边界:异步方法中的事务与发布者事务独立,需注意数据一致性。
四、适用场景
  • 业务解耦:将核心流程与子流程(如日志记录、数据统计)分离。
  • 异步处理:非实时任务(邮件、短信、文件导出)。
  • 事件驱动架构:微服务间通过事件通知实现最终一致性。

通过 Spring Boot Event,可以以轻量级方式实现业务解耦,避免引入 MQ 等复杂组件,同时支持同步与异步两种模式,满足不同场景需求。