- 直接注入我们的ApplicationEventPublisher,使用@Autowired注入一下 。
@SpringBootTestclass SpirngEventApplicationTests {@AutowiredApplicationEventPublisher appEventPublisher;@Testvoid contextLoads() {appEventPublisher.publishEvent(new UserChangePasswordEvent("1111111"));}}我们执行一下看一下接口 。
文章插图
测试成功 。
搭配@Async注解实现异步操作监听器默认是同步执行的,如果我们想实现异步执行,可以搭配@Async注解使用,但是前提条件是你真的懂@Async注解,使用不当会出现问题的 。 后续我会出一篇有关@Async注解使用的文章 。这里就不给大家详细的解释了 。有想了解的同学可以去网上学习一下有关@Async注解使用 。
使用@Async时,需要配置线程池,否则用的还是默认的线程池也就是主线程池,线程池使用不当会浪费资源,严重的会出现OOM事故 。
下图是阿里巴巴开发手册的强制要求 。

文章插图
简单的演示一下:这里声明一下俺没有使用线程池,只是简单的演示一下 。
- 在我们的启动类上添加@EnableAsync开启异步执行配置
@EnableAsync@SpringBootApplicationpublic class SpirngEventApplication {public static void mAIn(String[] args) {SpringApplication.run(SpirngEventApplication.class, args);}}- 在我们想要异步执行的监听器上添加@Async注解 。
/** * @Author JiaQIng * @Description 事件监听器 * @ClassName LogListener * @Date 2023/3/26 14:22 **/@Componentpublic class ListenerEvent {@Async@EventListener({ UserChangePasswordEvent.class })public void logListener(UserChangePasswordEvent event) {System.out.println("收到事件:" + event);System.out.println("开始执行业务操作生成关键日志 。用户userId为:" + event.getUserId());}} 这样我们的异步执行监听器的业务操作就完成了 。
Spring的事件机制的应用场景
- 告警操作,比喻钉钉告警,异常告警,可以通过事件机制进行解耦 。
- 关键性日志记录和业务埋点,比喻说我们的关键日志需要入库,记录一下操作时间,操作人,变更内容等等,可以通过事件机制进行解耦 。
- 性能监控,比喻说一些接口的时长,性能方便的埋点等 。可以通过事件机制进行解耦 。
- .......一切与主业务无关的操作都可以通过这种方式进行解耦,常用的场景大概就上述提到的,而且很多架构的源码都有使用这种机制,如GateWay,Spring等等 。
- 对于同一个事件,有多个监听器的时候,注意可以通过@Order注解指定顺序,Order的value值越小,执行的优先级就越高 。
- 如果发布事件的方法处于事务中,那么事务会在监听器方法执行完毕之后才提交 。事件发布之后就由监听器去处理,而不要影响原有的事务,也就是说希望事务及时提交 。我们就可以 @TransactionalEventListener来定义一个监听器 。
- 监听器默认是同步执行的,如果我们想实现异步执行,可以搭配@Async注解使用,但是前提条件是你真的懂@Async注解,使用不当会出现问题的 。
- 对于同一个事件,有多个监听器的时候,如果出现了异常,后续的监听器就失效了,因为他是把同一个事件的监听器add在一个集合里面循环执行,如果出现异常,需要注意捕获异常处理异常 。
推荐阅读
- 使用Go语言进行开发的互联网公司
- 灭火器的使用方法口诀是什么
- 白衣天使,真的是一份神仙职业吗?
- 使用走珠液要注意什么
- 热水器省电的正确用法有哪些 热水器省电使用方法
- 秒表的使用 秒表的使用方法
- 十个很少使用的 JavaScript Console 方法
- 使用Java Reflection实现对象的动态操作与扩展
- Spring中Bean的作用域Scope你知道多少?如何自定义作用域?
- 如何使用Python构建一个抄袭检测系统?
