Spring事件,ApplicationEvent在业务中的应用
2021-10-17 19:17
841 查看
前言
关于事件驱动模型,百度百科在有明确的解释。在
JDK的Util包里抽象了事件驱动,有兴趣的朋友可以自行去看下相关类的定义。Spring事件模型ApplicationEvent是基于JDK里的事件模型,废话不多说,直接看Spring是如何定义事件模型,以及在具体业务场景中的应用。
事件
事件就是事件,鼠标点击一下算一个事件,某个按钮被点击了一下算一个点击事件,那么我订单支付了可以认为支付也算一个件事!触发了某个事件...... 等等。
抽象类
ApplicationEvent承载着我们要传播的事件或者消息,白话就是说可以把某个对象用
ApplicationEvent这个对象来里的
Source来引用。
监听者
上面我们定义了事件,那么事件产生的一系列的效应或者是变动,那么都由这些监听者们去实现。点击下鼠标(事件),那么我记录下日志,你弹出个提示框。支付某个订单(事件),我记录下记录,他发送个支付通知...... 等等。
泛型接口
ApplicationListener规定了泛型E的上边界为
ApplicationEvent,意思很明确,就是给我们自定义事件用的。
Spring最大的优点我认为是留给用户发挥的空间很大,就像神秘的海洋一样,它一直有你探索不完的秘密,每一次你去了解它,它都能给你带来新的事物和理解。
实战
文章SpringPlugin-Core在业务中的应用中,我们用
SpringPlugin插件的方式去实现了订单的不同操作!而在某个操作里面,我们可能又要发送操作事件的通知,比如:订单支付了后,要通知打印机打印小票、微信公众号提醒支付信息等等。那么我们来实际的操作下。
定义事件源
public class OrderPayedEvent extends ApplicationEvent { /** * 消息体,这里就设定为当前订单对象 */ private final Order order; public OrderPayedEvent(Object source) { super(source); this.order = (Order) source; } public Order getOrder() { return order; } }
实现
ApplicationEvent, 我这里
Source实际传递就是
Order对象,当然你也可以定义其他的多参数构造函数!
定义监听者
定义监听者的方式,
Spring提供了两种,一种是接口方式,一种是注解方式。
接口方式
@Component @Order(1) public class OrderPayedPrinterListener implements ApplicationListener<OrderPayedEvent> { @Override public void onApplicationEvent(OrderPayedEvent event) { System.out.printf("【线程 - %s 】订单成功成功:第一步,打 1044 印小票%n", Thread.currentThread().getName()); } } @Component @Order(2) public class OrderPayedSendMessageListener implements ApplicationListener<OrderPayedEvent> { @Override public void onApplicationEvent(OrderPayedEvent event) { System.out.printf("【线程 - %s 】订单成功成功:第二步,发送通知商品中心添加库存%n", Thread.currentThread().getName()); } }
这里我定义了两个监听者,实现泛型接口
ApplicationListener类型为我们刚定义的
OrderPayedEvent这里加上
Order注解,是因为我们有多个监听者,有此业务场景中可能会有顺序的要求!
注解方式
@Component public class OrderPayListener { @EventListener(classes = {OrderPayedEvent.class}) public void sendTips(OrderPayedEvent event) { System.out.printf("【线程 - %s 】订单成功成功:发送用户订单支付消息%n", Thread.currentThread().getName()); } @EventListener(classes = {OrderPayedEvent.class}) public void reward(OrderPayedEvent event) { System.out.printf("【线程 - %s 】订单成功成功:奖励业务%n", Thread.currentThread().getName()); } }
两种方式,各有千秋,不同业务场景选择不同实现方式即可。但注解方式是不会有排序功能的,如果你有业务有需要排序,那么建议换成接口方式
发布件事
万事具备,只欠东风。那么只要合适的位置发布事件即可,那么在上回文章中的支付成功代码加上事件即可
@Component public class PayOperator implements OrderOperatorPlugin { //这里注入 应用上下文,可以注入 applicationEventPublisher @Resource ApplicationContext context; // @Resource // ApplicationEventPublisher applicationEventPublisher; @Override public Optional<?> apply(OrderOperatorDTO operator) { //支付操作 //doPay() //发送事件 context.publishEvent(new OrderPayedEvent(new Order())); return Optional.of("支付成功"); } @Override public boolean supports(OrderOperatorDTO operatorDTO) { return operatorDTO.getOperatorType() == OrderOperatorType.PAY; } }
打印如下:
【线程 - main 】订单成功成功:第一步,打印小票 【线程 - main 】订单成功成功:第二步,发送通知商品中心添加库存 【线程 - main 】订单成功成功:第四步,奖励业务 【线程 - main 】订单成功成功:第三步,发送用户订单支付消息
那么,ApplicationEvent
对异步支持是怎么样的呢?
只要在启动类上加上
@EnableAsync,在方法体加上
@Async
再打印如下:
【线程 - task-1 】订单成功成功:第一步,打印小票 【线程 - task-2 】订单成功成功:第二步,发送通知商品中心添加库存 【线程 - task-4 】订单成功成功:第四步,奖励业务 【线程 - task-3 】订单成功成功:第三步,发送用户订单支付消息
总结
不管是
EventObject,还是
Observable模型,都是用来解耦代码。高内聚,低耦合的设计思想一至到现在都没有被突破过,也是我们在日常工作过程中时刻要提醒自己的编码思想。而我们更要利用好这些前人留下的精髓,应用到我们实际的业务场景中去。
[代码在GitHub](
相关文章推荐
- springBoot事件监听 在项目实际业务中的异步应用
- SpringPlugin-Core在业务中的应用
- spring4.2的应用事件
- spring学习笔记(15)趣谈spring 事件:实现业务逻辑解耦,异步调用提升用户体验
- Spring中的事件监听机制在项目中的应用
- Spring入门学习——使用应用事件进行通信
- 从spring源码汲取营养:模仿spring事件发布机制,解耦业务代码
- 《BREW进阶与精通——3G移动增值业务的运营、定制与开发》连载之79——BREW应用间通信之事件传递
- Spring中的事件监听机制在项目中的应用
- 《BREW进阶与精通――3G移动增值业务的运营、定制与开发》连载之79――BREW应用间通信之事件传递
- Spring中的事件监听机制在项目中的应用
- Spring中的事件监听机制在项目中的应用
- springboot源码分析14-事件发布机制以及应用监听器
- 利用spring事件和监听机制实现容器启动时的构建某业务服务类容器(Map)
- SpringBoot+ZooKeeper+ZKUI+Drools 实现应用配置中心及业务规则动态加载
- Spring事务是如何应用到你的业务场景中的?
- 基于Spring事件监听的业务处理
- 熟悉公司业务springboot和dataTable和validate在项目中的应用(1)
- Spring在Web应用中的事件与使用
- Spring在Web应用中的事件与使用