前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >事件监听思考

事件监听思考

作者头像
路行的亚洲
发布于 2022-11-16 06:46:14
发布于 2022-11-16 06:46:14
2.2K00
代码可运行
举报
文章被收录于专栏:后端技术学习后端技术学习
运行总次数:0
代码可运行

在整合在项目中,我们通常需要基于事件去触发另外的业务逻辑动作的完成。也即在我们做需求时,通常会基于不同的事件码来完成业务处理,此时可以考虑将其单独处理,基于观察者模式+策略模式。还有一种如果当Spring完成Bean的初始化,需要做一些特殊处理,此时除了使用InitializingBean,还可以使用监听完成一些定制化的初始化动作,实现ApplicationListener<ContextRefreshedEvent>。

也即一种方式是实现一个上下文,基于不同的事件码去实现对应的业务处理场景,此时可以基于监听,分不同的策略实现处理。另一种则是通常是完成Bean初始化后,如果当前需要自定义的配置信息或者服务没有完成的场景。如果你看过dubbo3.0的源码的话,你会发现dubbo-config-spring模块,使用到了事件监听的方式执行发布和监听。

一、实现ApplicationListener<ContextRefreshedEvent>的场景

防止重复触发:

比如:ContextRefreshedEvent是上下文刷新事件,在初始化后执行的事件,当完成初始化后触发,从而执行监听。这个事件在完成初始化执行。同时其避免了重复触发的情况。下面的代码是在Spring完成Bean的初始化后,经过上下文刷新事件后,执行的,同时可以根据监听对象的顺序依次进行触发。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class MqBootstrapListener implements ApplicationListener<ContextRefreshedEvent>, Ordered {

    private static boolean isInit = false;
    @Autowired
    private ReportService reportService;
    @Override
    public int getOrder() {
        // 执行顺序定义
        return Ordered.LOWEST_PRECEDENCE;
}

    //触发的事件启动相关业务,同时将初始化变成true
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (!isInit) {
            try {
                startTimer();
                startPortalTimer();
                reportService.registerReport();
                isInit = true;
                log.info("mq初始化成功!");
            } catch (Exception e) {
                log.error("mq初始化异常", e);
                throw e;
            }
        }

}

这种效果类似于实现InitializingBean接口,会调用afterPropertiesSet方法,也即执行Bean初始化后自己实现的方法。此时的发布事件是基于Spring的。

类似的过程在Spring做xml的默认解析时候,就会使用到。完成xml解析的时候,会做一个事件的发布。后续的操作留给了业务实现。

那么我们能不能自己发布事件,然后自己去监听呢?答案当然是可以的。

二、基于自己实现的事件发布和事件监听

通常一种常用的做法是先定义好类型,这样的话,可以基于类型进行key是类型,value为具体的接口实现,基于当前的key和value放到map中。这样在需要获取的时候,可以基于code获取对应的渠道服务,从而实现对不同类型的key,做到对应的业务处理。

比如: 我的业务服务订单服务中,需要基于订单提交后审批流做一个订单对应状态的更新和业务的处理。此时由于审核的情况不同,会出现不同的订单状态。那么,我们对于不同的订单状态,处理的业务方式是不同的。因此,可以考虑基于策略者模式+观察者模式完成完成订单状态和业务的处理。

审批流完成后,由于审批的结果,导致订单的状态不同,而进行财务对应服务更新时,做的处理时不一样的。

订单出现的状态:

订单审批通过

订单审批取消

更新订单

新增订单

因此就需要我们能够在不影响后续逻辑处理的情况下可以将一部分繁杂的逻辑基于事件发布的方式独立发布出来进行处理,采用异步的方式处理。这样做一个时方便后续的业务的处理,同时对应业务繁杂处理时,能够快速处理。

首先执行事件发布:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  @Override
    public Integer auditUpdateStatus(TaskResearchDTO taskResearchVO) {
        OrderApprovalPO orderApprovalPO = orderApprovalMapper.selectById(taskResearchVO.getBusinessKey());
        SalesOrdersPO salesOrdersPO = salesOrdersMapper.selectById(orderApprovalPO.getSoNoId());
        QueryWrapper<SalesOrderVinPO> queryWra = new QueryWrapper<>();
        queryWra.lambda().eq(SalesOrderVinPO::getViNo, salesOrdersPO.getSoNo());
        SalesOrderVinPO salesVinPO = salesOrderVinMapper.selectOne(queryWra);
        salesOrdersPO.setUpdatedAt(LocalDateTime.now());
        salesVinPO.setUpdatedAt(LocalDateTime.now());
        //发布事件
        applicationEventPublisher.publishEvent(new MessageEvent(this, orderApprovalPO.getAuditType(),orderApprovalPO,salesOrdersPO,salesVinPO));
        salesOrderVinMapper.updateById(salesVinPO);
        int result = salesOrdersMapper.updateById(salesOrdersPO);
        Integer auditType = orderApprovalPO.getAuditType();
        if(SalesCommonDictConstants.APPROVAL_TYPE_ADD_ORDER.equals(auditType) || SalesCommonDictConstants.APPROVAL_TYPE_UPDATE_ORDER.equals(auditType)){
            leadTimesSnapshotService.saveCompensation(salesOrdersPO);
        }
        return result;
    }

基于发布,我们可以写一个自己的监听,然后处理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Component
public class OrderListener implements ApplicationListener<MessageEvent> {

    @Autowired
    private AuditContext saveContext;

    @Override
    public void onApplicationEvent(MessageEvent event) {
       saveContext.resolveFile(event.getAuditType(), event.getOrderApprovalPO(), event.getSalesOrdersPO(), event.getSalesOrderVinPO());
    }
}

然后基于不同的type,做类型的路由

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class AuditContext implements ApplicationContextAware {
    public static final Logger log = LoggerFactory.getLogger(AuditContext.class);
    /**
     * 将策略存放在map中
     */
    private Map<Integer, AuditTypeStrategy> activityStrategyMap = new ConcurrentHashMap<>();

    /**
     * 获取对应策略
     */
    public void resolveFile(int type, OrderApprovalPO orderApprovalPO, SalesOrdersPO salesOrdersPO, SalesOrderVinPO salesVinPO) {
        AuditTypeStrategy auditTypeStrategy = activityStrategyMap.get(type);
        if (auditTypeStrategy != null) {
            auditTypeStrategy.auditUpdateStatus(orderApprovalPO, salesOrdersPO, salesVinPO);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //获取AuditTypeStrategy接口所有的实现
        Map<String, AuditTypeStrategy> tmepMap = applicationContext.getBeansOfType(AuditTypeStrategy.class);
        //存入上面的map中
        tmepMap.values().forEach(strategyService -> activityStrategyMap.put(strategyService.getAuditType(), strategyService));
    }
}

当传入对应的type的时候,可以拿到具体的service实现,从而对具体的业务进行处理。

通常第一种使用的场景比如:初始化字典的相关信息、redis缓存的相关信息、系统信息或者定时任务等等。第二种使用场景,比如需要发布一个事件,可以方便业务的处理,或者处理的过程较为繁琐的时候,就可以使用,easyExcel的导入使用的就是基于监听的方式进行处理的,或者当前业务处理情况有多种的时候,就可以考虑使用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端技术学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring - 事件监听机制 源码解析
众所周知,Spring Framework在 BeanFactory的基础容器之上扩展为了ApplicationContext上下文。 ApplicationContext处理包含了BeanFactory的全部基础功能之外,还额外提供了大量的扩展功能。
小小工匠
2022/12/18
3680
Spring - 事件监听机制 源码解析
Spring高手之路7——事件机制与监听器的全面探索
观察者模式是一种行为设计模式,它定义了对象之间的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。在这个模式中,改变状态的对象被称为主题,依赖的对象被称为观察者。
砖业洋__
2023/07/06
1.7K0
Spring高手之路7——事件机制与监听器的全面探索
Spring容器的事件监听机制(简单明了的介绍)
上一篇我们介绍了SpringFactoriesLoader。这一篇我接着来介绍一下Spring的另一个知识点,就是Spring容器的事件监听机制。
码农飞哥
2021/08/18
5900
Spring 事件监听机制源码
Spring 提供了许多非常好用的机制,比如IOC,AOP。这些几乎在所有的Spring项目中都有广泛的使用,这里讲解的是Spring提供的事件发布订阅机制,掌握发布订阅设计模式可以更好的在项目中对功能进行设计,也多一种解决方案。同时如果你掌握了SpringBoot的事件发布的全部流程,你就掌握了SpringBoot在整个启动过程中干了什么事,走了哪些流程
每周聚焦
2024/10/11
1740
Spring 事件监听机制源码
《Spring 手撸专栏》第 11 章:更上层楼,基于观察者实现,容器事件和事件监听器
摔杯为号、看我眼色行事、见南面火起,这是在嘎哈么?这其实是在通过事物传播进行解耦引线和炸弹,仅仅是这样的一个解耦,它放到了多少村夫莽汉,劫了法场,篡了兵权!
小傅哥
2021/07/23
2570
Spring | 事件监听器应用与最佳实践
在复杂的软件开发环境中,组件之间的通信和信息交流显得尤为重要。Spring框架,作为Java世界中最受欢迎的开发框架之一,提供了一种强大的事件监听器模型,使得组件间的通信变得更加灵活和解耦。本文主要探讨Spring事件监听器的原理、使用方法及其在实际开发中的应用,希望为广大开发者提供实用的参考。
kfaino
2023/09/25
2.1K0
Spring | 事件监听器应用与最佳实践
spring的事件监听应用场景_java监听器的原理与实现
Spring 从 3.x 开始支持事件机制。在 Spring 的事件机制中,我们可以令一个事件类继承 ApplicationEvent 类,然后将实现了 ApplicationListener 的 Bean 注册到 spring 容器,最后向 ApplicationEventPublisher 推送事件对象即可令所有订阅者收到事件。在 4.2 以后,甚至不需要实现 ApplicationListener 接口,仅需在 Bean 中方法标记 @EventListener 注解即可。
全栈程序员站长
2022/09/23
9260
Spring高手之路15——掌握Spring事件监听器的内部逻辑与实现
在Spring中,ApplicationContext可以形成一个层次结构,通常由主容器和多个子容器组成。一个常见的疑问是:当一个事件在其中一个容器中发布时,这个事件会如何在这个层次结构中传播?
砖业洋__
2023/10/27
8020
Spring高手之路15——掌握Spring事件监听器的内部逻辑与实现
4 Spring源码 --- 监听器的原理
为什么要学习监听器呢?学习监听器主要学习监听器的设计思想。 比如,我们之前研究过的nacos,他就是使用监听器进行集成的。所以了解监听器的原理,就很重要了。
用户7798898
2020/12/03
1.5K0
4 Spring源码 --- 监听器的原理
理解 Spring ApplicationListener
ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext事件处理。
全栈程序员站长
2022/11/18
2190
掌握 Spring 之事件处理
1 前言2.1 Spring 标准事件处理2.1.1 注解驱动的事件侦听引入 @EventListener事件的传递2.1.2 侦听器优先级2.2 自定义事件2.2.1 自定义 Application Event2.2.2 自定义 Publisher2.2.3 自定义 Listener2.2.4 异步事件处理2.3 Spring Boot 事件与侦听3 结语4 参考
闻人的技术博客
2019/09/19
1.3K0
探索Spring事件监听机制的奇妙世界
Spring事件监听机制是一种在Spring应用程序中处理事件和消息的机制。它基于观察者模式,允许定义事件源、事件监听器和事件对象,以便在特定事件发生时执行自定义逻辑。
索码理
2023/11/08
3000
Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析
Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析
小小工匠
2021/08/17
8360
【小家Spring】从Spring中的(ApplicationEvent)事件驱动机制出发,聊聊【观察者模式】【监听者模式】【发布订阅模式】【消息队列MQ】【EventSourcing】...
说到事件驱动,我心里一直就有一个不解的疑问:它和我们老生长谈的一些概念比如:【观察者模式】【发布订阅模式】【消息队列MQ】【消息驱动】【EventSourcing】等等是一回事吗?
YourBatman
2019/09/03
7K0
【小家Spring】从Spring中的(ApplicationEvent)事件驱动机制出发,聊聊【观察者模式】【监听者模式】【发布订阅模式】【消息队列MQ】【EventSourcing】...
Spring中的事件
文章目录 1. 简介 2. 事件 2.1. Spring中内置的事件 2.2. 自定义事件 3. 监听器 3.1. 实现ApplicationListener接口 3.2. 使用@EventListener注解 4. 事件发布 4.1. Spring的事件发布类 4.2. 直接注入 4.3. 使用ApplicationEventPublisherAware注入 5. 事件多播器 6. 异步事件 6.1. 使用@Async实现异步 6.2. 自定义事件多播器 7. 源码解析 简介 学过编程语言的肯定知道事
爱撒谎的男孩
2019/12/31
1.3K0
ApplicationListener 和@EventListener 注解实现事件监听
对于 Spring 容器的一些事件,可以监听并且触发相应的方法。通常的方法有 2 种,ApplicationListener 接口和@EventListener 注解。
水货程序员
2018/11/13
10.2K0
六种方式实现 springboot 项目 启动预加载
在实际工作中总是需要在项目启动时做一些初始化的操作,比如初始化线程池、提前加载好加密证书…
猫头虎
2024/04/07
5730
六种方式实现 springboot 项目 启动预加载
Spring之事件机制详解
Spring提供了事件机制,其本质是JDK提供的事件机制的应用,利用的是观察者设计模式,具体请看设计模式之观察者模式(Observer Pattern)。 这里我们来分析Spring事件机制的原理。 先上UML图,不熟悉UML规则的可以看UML类图的制作规则。
猫头虎
2024/04/07
1310
Spring之事件机制详解
源码级别的广播与监听实现
近期疫情形势严峻,情形不容乐观,周末也不敢出去浪了,躲在家里“葛优躺”。闲来无事,又翻了遍Spring的源码。不翻不知道,一翻吓一跳,之前翻过的源码已经吃进了肚子里,再见亦是陌生人。
阿Q说代码
2022/05/23
3560
源码级别的广播与监听实现
面试官来了:说说你对Spring事件发布&监听源码的理解?
之前做个数据统计的需求,就是用的Spring事件发布与监听机制(用于采集基础数据),今天做个小小的总结。
后台技术汇
2022/05/28
3930
面试官来了:说说你对Spring事件发布&监听源码的理解?
推荐阅读
相关推荐
Spring - 事件监听机制 源码解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档