2.3.基于异步事件处理
@Async是Spring框架中的一个注解,用于将一个方法标记为异步执行。使用该注解,Spring将自动为该方法创建一个新线程,使其在后台异步执行,不会阻塞主线程的执行。
在具体应用中,使用@Async可以大大提升应用的并发处理能力,使得系统能够更快地响应用户请求,提高系统的吞吐量。
@Async 和 @EventListener 或 @TransactionEventListener 注解在一起使用时,会产生异步的事件处理器。使用这种组合的方式,事件处理器会在单独的线程池中执行,以避免阻塞主线程。这种方式在需要处理大量事件或者事件处理器耗时较长的情况下非常有用,可以有效提高应用的性能和可伸缩性。同时,Spring 框架对这种方式也提供了完善的支持,可以方便地使用这种方式来实现异步事件处理。
下面是一个简单的示例代码,演示了如何在 Spring 中使用 @Async 和 @EventListener 一起实现异步事件处理:
@Component public class ExampleEventListener { @Async @EventListener public void handleExampleEvent(ExampleEvent event) { // 在新的线程中执行异步逻辑 // ... } }
在这个示例中,ExampleEventListener 类中的 handleExampleEvent 方法使用了 @Async 和 @EventListener 注解,表示这个方法是一个异步事件监听器。当一个 ExampleEvent 事件被触发时,这个方法会被异步地执行。在这个方法中,可以执行任何异步的逻辑处理,比如向队列发送消息、调用其他服务等。
备注:在使用 @Async 时,需要根据业务场景对线程池进行自定义,以免出现资源不够的情况(Spring 默认使用单线程处理@Async异步任务)
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
4. 场景分析
综上所述,当领域事件发出来之后,不同的注解会产生不同的行为,简单汇总如下:
@EventListener | @TransactionEventListener | |
无 @Async | 顺序、同步执行 | 事务提交后、同步执行 |
有 @Async | 顺序、异步执行 | 事务提交后、异步执行 |
4.1. @EventListener
特点:
- 顺序执行。调用 publish(Event) 后,自动触发对 @EventListner 注释方法的调用
- 同步执行。使用主线程执行,方法抛出异常会中断调用链路,会触发事务的回归
应用场景:
- 事务消息表。在同一事务中完成对业务数据和消息表的修改
- 业务验证。对业务对象进行最后一次验证,如果验证不通过直接抛出异常中断数据库事务
- 业务插件。在当前线程和事务中执行插件完成业务扩展
4.2. @TransactionEventListener
特点:
- 事务提交后执行。调用 publish(Event) 时,只是向上下文中注册了一个回调器,并不会立即执行;只有在事务提交后,才会触发对 @TransactionEventListner 注释方法的调用
- 同步执行。使用主线程执行,方法抛出异常会中断调用链路,当不会回归事务(事务已提交,没有办法进行回归)
应用场景:
- 数据同步。事务提交后,将变更同步到 ES 或 Cache
- 记录审计日志。只有在业务变更成功更新到数据库时才进行记录
备注:@TransactionEventLisnter 必须在事务上下文中,脱离上下文,调用不会生效
4.3. @EventListener + @Async
特点:
- 顺序执行。调用 publish(Event) 后,自动触发对 @EventListner 注释方法的调用
- 异步执行。使用独立的线程池执行任务,方法抛出异常对主流程没有任何影响
应用场景:
- 记日志明细日志,辅助排查问题
4.4. @TransactionEventListener + @Async
特点:
- 事务提交后执行。调用 publish(Event) 时,只是向上下文中注册了一个回调器,并不会立即执行;只有在事务提交后,才会触发对 @TransactionEventListner 注释方法的调用
- 异步执行。使用独立的线程池执行任务,方法抛出异常对主流程没有任何影响
应用场景:异步处理。记录操作日志,异步保存数据等 备注:@TransactionEventLisnter 必须在事务上下文中,脱离上下文,调用不会生效
5. 小结
领域事件的落地,不仅需要强大的设计能力,还需要与之匹配的基础设施。Spring 作为最常用的框架,基于发布订阅实现了完整的一套 Event 管理机制。工具在手是否能根据业务场景选择合适的解决方案就成了研发的职责,简单思考以下组合适用场景是什么:
- @EventListener
- @TransactionEventListener
- @EventListener + @Async
- @TransactionEventListener + @Async