Spring事件机制让你的代码更优雅

今天为大家分享一下Spring的事件机制的使用,它是spring中一个非常好用也很实用的机制。

1. spring事件机制的概念

Spring的事件机制是基于观察者模式实现的,它可以在我们的实际应用程序中实现代码之间的解耦,提高代码的可维护性和可扩展性。

Spring的事件机制包括事件、事件发布、事件监听器等几个基本概念。

  • 事件是一个抽象的概念,它代表着应用程序中的某个动作或状态的发生。
  • 事件发布是事件发生的地方,它负责产生事件并通知事件监听器。
  • 事件监听器是事件的接收者,它负责处理事件并执行相应的操作。

在Spring的事件机制中,事件源和事件监听器之间可以通过事件进行通信,来实现模块之间的解耦,提高代码的优雅性和可维护性。

比如:用户修改密码,需要进行短信通知,记录关键性日志或者其他业务操作。
在这里插入图片描述

1.1 事件

通过继承ApplicationEvent,实现自定义事件。Spring 中的所有事件都要基于其进行扩展。其源码如下:
在这里插入图片描述

1.2 事件发布

事件发布是事件发生地,它负责产生事件并通知事件监听器。ApplicationEventPublisher用于发布 ApplicationEvent 事件,发布后 ApplicationListener 才能监听到事件进行处理。源码如下:
在这里插入图片描述

参数需要一个ApplicationEvent,就是我们的事件,然后通过该方法去发布我们的事件。

1.3 事件监听器

ApplicationListener 是 Spring 事件的监听器,用来接受事件,所有的监听器都必须实现该接口。该接口源码如下:
在这里插入图片描述

或者采用注解方式来实现:@EventListener。

2. 案例演示

2.1 定义事件

/**
 * @BelongsProject: ims-formworkflow-api
 * @BelongsPackage: com.wuk.imsformworkflowapi.client
 * @Author: wuk
 * @Date: 2023/6/13 9:54
 * @Description: 创建事件
 */
@Getter
@Setter
public class UserChangePasswordEvent extends ApplicationEvent {

    private String userId;

    public UserChangePasswordEvent(String userId) {
        super(new Object());
        this.userId = userId;
    }
}

这里就定义我们监听器需要的业务参数,我们需要监听器监听哪些参数的变化,我们就在这里定义哪些参数。

2.2 监听事件的实现

有两种方式,一种是通过实现接口方式,一种是注解方式,推荐使用注解,耦合性比较低,比较灵活。
方式一:

/**
 * @BelongsProject: ims-formworkflow-api
 * @BelongsPackage: com.wuk.imsformworkflowapi.client
 * @Author: wuk
 * @Date: 2023/6/13 9:57
 * @Description: 方式1:实现接口方式,实现监听逻辑
 */
@Component
public class MessageListener implements ApplicationListener<UserChangePasswordEvent> {
    @Override
    public void onApplicationEvent(UserChangePasswordEvent event) {
        System.out.println("监听者1:收到事件:" + event);
        System.out.println("监听者1:开始执行业务操作给用户发送短信。用户userId为:" + event.getUserId());
    }
}

方式二:

/**
 * @BelongsProject: ims-formworkflow-api
 * @BelongsPackage: com.wuk.imsformworkflowapi.client
 * @Author: wuk
 * @Date: 2023/6/13 10:24
 * @Description: 方式二:注解形式实现事件监听器
 */
@Component
public class ListenerEvent {

    @EventListener({ UserChangePasswordEvent.class })
    public void LogListener(UserChangePasswordEvent event) {
        System.out.println("监听者2:收到事件:" + event);
        System.out.println("监听者2:开始执行业务操作生成关键日志。用户userId为:" + event.getUserId());
    }

    @EventListener({ UserChangePasswordEvent.class })
    public void messageListener(UserChangePasswordEvent event) {
        System.out.println("监听者3:收到事件:" + event);
        System.out.println("监听者3:开始执行业务操作给用户发送短信。用户userId为:" + event.getUserId());
    }
}

注意:使用 @EventListener 注解的好处是一个类可以写很多监听器,定向监听不同的事件,或者同一个事件。

这里面还延伸了一个注解:@TransactionalEventListener,他与@EventListener不同的就是@EventListener标记一个方法作为监听器,他默认是同步执行

我们知道,Spring的事件监听机制实际上是同步的。来将代码进行解耦。而@TransactionEventListener仍是通过这种方式,但是加入了回调的方式来解决,这样就能够在事务进行Commited,Rollback…等时候才去进行Event的处理,来达到事务同步的目的。

2.3 事件发布

    @GetMapping("/eventTest")
    public R<Void> eventTest(){

        applicationEventPublisher.publishEvent(new UserChangePasswordEvent("11111"));

        return R.ok();
    }

执行完毕后,控制台打印如下:
在这里插入图片描述

3. 利用@Async实现事件异步

监听器默认是同步执行的,如果我们想实现异步执行,可以搭配@Async注解使用。

注意:使用@Async时,需要配置线程池,否则用的还是默认的线程池也就是主线程池,线程池使用不当会浪费资源,严重的会出现OOM事故。

我这边只做演示,就不创建线程池了。

3.1 启动类添加@EnableAsync开启异步执行配置

@EnableAsync
@SpringBootApplication
public class SpirngEventApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpirngEventApplication.class, args);
    }

}

3.2 在要异步执行的监听器上添加@Async注解

@Component
public class ListenerEvent {
    
    @Async
    @EventListener({ UserChangePasswordEvent.class })
    public void logListener(UserChangePasswordEvent event) {
        System.out.println("收到事件:" + event);
        System.out.println("开始执行业务操作生成关键日志。用户userId为:" + event.getUserId());
    }
}

4. 场景应用

  • 告警操作,比如钉钉飞书告警,异常告警,可以通过事件机制进行解耦。
  • 关键性日志记录和业务埋点。
  • 性能监控,比如说接口的时长,性能方便的监控等。可以通过事件机制进行解耦。

总之与主业务无关的操作都可以通过这种方式进行解耦。

5. 注意点

在使用spring事件中我们要注意如下问题:

  • 对于同一个事件,有多个监听器的时候,可以通过@Order注解指定顺序,Order的value值越小,执行的优先级就越高。
  • 如果发布事件的方法处于事务中,那么事务会在监听器方法执行完毕之后才提交。事件发布之后就由监听器去处理,而不要影响原有的事务,也就是说希望事务及时提交。我们就可以 @TransactionalEventListener来定义一个监听器。
  • 监听器默认是同步执行的,如果我们想实现异步执行,可以搭配@Async注解使用。
  • 对于同一个事件,有多个监听器的时候,如果出现了异常,后续的监听器就失效了,因为他是把同一个事件的监听器add在一个集合里面循环执行,如果出现异常,需要注意捕获异常处理异常。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本书是国内唯一一本系统分析Spring代码的著作,也是Spring领域的问鼎之作,由业界拥有10余年开发经验的资深Java专家亲自执笔,Java开发者社区和Spring开发者社区联袂推荐。本书第1版不仅在内容上获得了读者的广泛好评,而且在销量上也摘取了同类书的桂冠,曾经一度掀起Java类图书的销售热潮。第2版不仅继承了第1版在内容组织和写作方式上的优点,而且还根据广大读者的反馈改进了若干细节上的不足。为重要的是,结合Spring的最新版本对过时的内容进行了新,并增加了大量新内容,使本书趋近于完美。书从源代码的角度对Spring的内核和各个主要功能模块的架构、设计和实现原理进行了深入剖析。你不仅能从本书中参透Spring框架的优秀架构和设计思想,还能从Spring优雅的实现源码中一窥Java语言的精髓。本书在开篇之前对Spring的设计理念和整体架构进行了全面的介绍,能让读者从宏观上厘清Spring各个功能模块之间的关系;第一部分详细分析了Spring的核心:IoC容器和AOP的实现,能帮助读者了解Spring的运行机制;第二部分深入阐述了各种基于IoC容器和AOP的Java EE组件在Spring中的实现原理;第三部分讲述了ACEGI安全框架、DM模块以及Flex模块等基于Spring的典型应用的设计与实现。论你是Java程序员、Spring开发者,还是平台开发人员、系统架构师,抑或是对开源软件源代码着迷的代码狂人,都能从本书中受益。
spring技术内幕:深入解析spring架构与计原理(第2版)》是国内唯一一本系统分析spring代码的著作,也是spring领域的问鼎之作,由业界拥有10余年开发经验的资深java专家亲自执笔,java开发者社区和spring开发者社区联袂推荐。本书第1版不仅在内容上获得了读者的广泛好评,而且在销量上也摘取了同类书的桂冠,曾经一度掀起java类图书的销售热潮。第2版不仅继承了第1版在内容组织和写作方式上的优点,而且还根据广大读者的反馈改进了若干细节上的不足。为重要的是,结合spring的最新版本对过时的内容进行了新,并增加了大量新内容,使本书趋近于完美。 《spring技术内幕:深入解析spring架构与计原理(第2版)》从源代码的角度对spring的内核和各个主要功能模块的架构、设计和实现原理进行了深入剖析。你不仅能从本书中参透spring框架的优秀架构和设计思想,还能从spring优雅的实现源码中一窥java语言的精髓。本书在开篇之前对spring的设计理念和整体架构进行了全面的介绍,能让读者从宏观上厘清spring各个功能模块之间的关系;第一部分详细分析了spring的核心:ioc容器和aop的实现,能帮助读者了解spring的运行机制;第二部分深入阐述了各种基于ioc容器和aop的java ee组件在spring中的实现原理;第三部分讲述了acegi安全框架、dm模块以及flex模块等基于spring的典型应用的设计与实现。 无论你是java程序员、spring开发者,还是平台开发人员、系统架构师,抑或是对开源软件源代码着迷的代码狂人,都能从本书中受益。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术闲聊DD

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值