事件监听思考

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

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

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


一、实现ApplicationListener的场景

防止重复触发:

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

@ComponentpublicclassMqBootstrapListenerimplementsApplicationListener<ContextRefreshedEvent>, Ordered {
privatestaticbooleanisInit=false;
@AutowiredprivateReportServicereportService;
@OverridepublicintgetOrder() {
// 执行顺序定义returnOrdered.LOWEST_PRECEDENCE;
   }
//触发的事件启动相关业务,同时将初始化变成true@OverridepublicvoidonApplicationEvent(ContextRefreshedEventevent) {
if (!isInit) {
try {
startTimer();
startPortalTimer();
reportService.registerReport();
isInit=true;
log.info("mq初始化成功!");
      } catch (Exceptione) {
log.error("mq初始化异常", e);
throwe;
     }
   }
}

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

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

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


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

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

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

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

订单出现的状态:

   订单审批通过

   订单审批取消

   更新订单

   新增订单

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

首先执行事件发布:

@OverridepublicIntegerauditUpdateStatus(TaskResearchDTOtaskResearchVO) {
OrderApprovalPOorderApprovalPO=orderApprovalMapper.selectById(taskResearchVO.getBusinessKey());
SalesOrdersPOsalesOrdersPO=salesOrdersMapper.selectById(orderApprovalPO.getSoNoId());
QueryWrapper<SalesOrderVinPO>queryWra=newQueryWrapper<>();
queryWra.lambda().eq(SalesOrderVinPO::getViNo, salesOrdersPO.getSoNo());
SalesOrderVinPOsalesVinPO=salesOrderVinMapper.selectOne(queryWra);
salesOrdersPO.setUpdatedAt(LocalDateTime.now());
salesVinPO.setUpdatedAt(LocalDateTime.now());
//发布事件applicationEventPublisher.publishEvent(newMessageEvent(this, orderApprovalPO.getAuditType(),orderApprovalPO,salesOrdersPO,salesVinPO));
salesOrderVinMapper.updateById(salesVinPO);
intresult=salesOrdersMapper.updateById(salesOrdersPO);
IntegerauditType=orderApprovalPO.getAuditType();
if(SalesCommonDictConstants.APPROVAL_TYPE_ADD_ORDER.equals(auditType) ||SalesCommonDictConstants.APPROVAL_TYPE_UPDATE_ORDER.equals(auditType)){
leadTimesSnapshotService.saveCompensation(salesOrdersPO);
      }
returnresult;
  }

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

ComponentpublicclassOrderListenerimplementsApplicationListener<MessageEvent> {
@AutowiredprivateAuditContextsaveContext;
@OverridepublicvoidonApplicationEvent(MessageEventevent) {
saveContext.resolveFile(event.getAuditType(), event.getOrderApprovalPO(), event.getSalesOrdersPO(), event.getSalesOrderVinPO());
  }
}

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

@ComponentpublicclassAuditContextimplementsApplicationContextAware {
publicstaticfinalLoggerlog=LoggerFactory.getLogger(AuditContext.class);
/*** 将策略存放在map中*/privateMap<Integer, AuditTypeStrategy>activityStrategyMap=newConcurrentHashMap<>();
/*** 获取对应策略*/publicvoidresolveFile(inttype, OrderApprovalPOorderApprovalPO, SalesOrdersPOsalesOrdersPO, SalesOrderVinPOsalesVinPO) {
AuditTypeStrategyauditTypeStrategy=activityStrategyMap.get(type);
if (auditTypeStrategy!=null) {
auditTypeStrategy.auditUpdateStatus(orderApprovalPO, salesOrdersPO, salesVinPO);
      }
  }
@OverridepublicvoidsetApplicationContext(ApplicationContextapplicationContext) throwsBeansException {
//获取AuditTypeStrategy接口所有的实现Map<String, AuditTypeStrategy>tmepMap=applicationContext.getBeansOfType(AuditTypeStrategy.class);
//存入上面的map中tmepMap.values().forEach(strategyService->activityStrategyMap.put(strategyService.getAuditType(), strategyService));
  }
}

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


三、使用场景

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

目录
相关文章
|
安全 网络协议 网络安全
网站被攻击了该怎么办?如何恢复网站,如何避免网站被攻击?
网站被攻击了该怎么办?如何恢复网站,如何避免网站被攻击?
|
6月前
|
存储 弹性计算 关系型数据库
阿里云服务器4核16G可选实例规格、收费标准、适用场景及活动价格
阿里云4核16G云服务器提供多样化实例规格,满足不同场景需求。收费模式灵活,支持按量付费和包年包月,其中包年包月性价比最高。目前4核16G配置选择经济型e实例的活动价格为2174.57元起,通用算力型u2i实例1576.80元起,通用型g9i实例3944.23元起。
|
9月前
|
人工智能 Cloud Native 数据管理
Gartner®全球云数据库管理系统魔力象限:阿里云连续6年获评“领导者”
Gartner®公布2025年度全球《云数据库管理系统魔力象限》报告。阿里云成为亚太区唯一入选该报告“领导者(LEADERS)”象限的科技企业,同时也是唯一一家连续6年位居“领导者”象限的中国企业。对阿里云而言,本次再度入选代表着其全栈云原生能力、面向AI时代的多模数据管理架构以及完整的Data+AI平台服务体系得到了高度认可,也充分彰显了阿里云在全球云数据库领域的行业引领地位,并印证了其在AI就绪时代的战略前瞻性。
|
7月前
|
机器学习/深度学习 弹性计算 人工智能
透明报价:阿里云服务器多少钱一年?2026年最新购买、续费及升级收费价格表
2026年阿里云服务器价格全解析:轻量应用服务器低至38元/年,ECS普惠款99元/年起,GPU实例支持AI算力需求。涵盖包年包月、按量付费三大计费模式,详解续费同价、多年付3.9折、升级差额补价等核心规则,助您精准控本、避坑省钱。(239字)
|
10月前
|
JSON 监控 API
京东商品列表API实战:关键词搜索与数据获取全指南
京东商品列表API是京东开放平台的核心接口,支持通过关键词搜索获取商品数据,适用于电商分析、竞品监控等场景。具备分类筛选、价格区间、多维度排序和分页功能,采用HTTPS请求,返回JSON格式数据,包含商品ID、名称、价格、销量等信息,支持高并发与实时更新。
|
Ubuntu Linux 定位技术
在Ubuntu 20.04系统安装Matlab R2021a步骤
希望你可以充分享受这场旅行,从无知的迷雾中找到通向智慧的路。好好装备你的 Linux 旅行箱吧,因为还有很多其他的知识世界等待你去探索和征服。在知识的海洋里,只有勇敢的探索者才能找到自己的道路。快乐旅行!
1508 23
|
Web App开发 JSON 搜索推荐
旺旺商聊群发器批量,阿里旺旺私信群发脚本,淘宝商家卖家私信插件工具
使用Selenium模拟浏览器操作实现淘宝/阿里旺旺自动登录和私信发送 支持从JSON文件加载消息模板和联系人列表
|
数据采集 机器学习/深度学习 算法
数据治理之参考数据与主数据管理
最近凑巧参与了一次某行业的业务共创会议,期间讨论到了主数据系统,还有我们该如何参与主数据系统建设的话题。说实话,我一直以为我不会有机会参与到主数据与参考数据系统的话题中去,所以,又去把DAMA的书籍翻了翻。顺便也重新思考了一下主数据与参考数据这个数据治理的课题。
3612 1
数据治理之参考数据与主数据管理
|
机器学习/深度学习 算法 算法框架/工具
改进的yolo目标检测(yolo创新与改进)
改进的yolo目标检测(yolo创新与改进)
|
存储 人工智能 编译器
【AI系统】CPU 指令集架构
本文介绍了指令集架构(ISA)的基本概念,探讨了CISC与RISC两种主要的指令集架构设计思路,分析了它们的优缺点及应用场景。文章还简述了ISA的历史发展,包括x86、ARM、MIPS、Alpha和RISC-V等常见架构的特点。最后,文章讨论了CPU的并行处理架构,如SISD、SIMD、MISD、MIMD和SIMT,并概述了这些架构在服务器、PC及嵌入式领域的应用情况。
2100 5