一、前言
二、业务解耦之事件监听实战
        1.事件监听三大组件
         2.事件发布以及监听实战案例
         3.事件发布以及监听原理

一、前言

耦合这个词在平常的开发工作中应该不陌生,简单理解就是代码中各部分关联度过高。举一个大家都遇见过的经典耦合场景:用户注册成功之后需要进行发送短信通知或是邮件通知,用户注册逻辑与发送短信或是邮件通知逻辑放在一块就是一种耦合现象,如果短信或是邮件功能异常,整个用户注册功能就会异常,会带来不好的用户体验,另外的缺点是维护复杂,不便于拓展。将业务逻辑与功能性逻辑进行拆分开就是属于解耦。spring中IOC思想就是解耦的一种体现,毕竟在一个实现类中如果调用另一个实现类不用繁琐的创建对象,只需要把需要用到实现类进行注入就可以了,减少代码量的同时也便于后期的拓展与维护。本文主要解决的问题就是在平常的开发中,如何将业务代码与固定功能性代码进行剥离,就是如何实现业务解耦。本文介绍一种解耦的实现思路:spring事件监听实现解耦。

二、业务解耦之事件监听实战

1.事件监听三大组件

关于事件监听大家都听过,现在重新认识一下事件监听的三个重要部分:
    1.1 事件源
    可以理解为事件类型。比如说我们将的发送邮件或是发送短信都算是一种事件类型,都可以叫做事件源。
    1.2 事件发布器
    事件发布器也可以称作事件发布者,主要作用是发布事件,一般用于业务逻辑完成之后进行事件发布。
    1.3 事件监听器
    主要作用就是监听是否有事件发布,如果有则执行对应的业务处理。
三者之间的关系流程如下:

2.事件发布以及监听实战案例

下面以预约课程成功之后需要发送消息提醒为例讲解一下如何利用监听器实现业务解耦。
    首先定义事件源,需要继承spring中事件的顶级父类,实现如下:

public class NewsEvent extends ApplicationEvent {// 消息发送具体内容private String newsInfo;public NewsEvent(String newsInfo) {super(newsInfo);this.newsInfo=newsInfo;}
}

定义事件发布器,这里有两种实现方式,分别是使用实现ApplicationEventPublisherAware.java或是实现ApplicationContextAware.java.
    自定义事件发布器实现ApplicationEventPublisherAware.java接口:

@Service
@Slf4j
public class TestServiceImpl implements TestService,ApplicationEventPublisherAware {private ApplicationEventPublisher applicationEventPublisher;@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher=applicationEventPublisher;}@Overridepublic void applyCourse() {log.info("课程预约成功");// 消息发送事件发布NewsEvent sendNewsEvent = new NewsEvent("课程预约成功发送消息事件");applicationEventPublisher.publishEvent(sendNewsEvent);}
}

自定义事件发布器实现ApplicationContextAware .java接口:

@Service
@Slf4j
public class TestServiceImpl implements TestService,ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext=applicationContext;}@Overridepublic void applyCourse() {log.info("课程预约成功");// 消息发送事件发布NewsEvent sendNewsEvent = new NewsEvent("课程预约成功发送消息事件");applicationContext.publishEvent(sendNewsEvent);}
}

最后定义事件监听器,实现方式也有两种,一种是实现ApplicationListener接口,实现逻辑如下:

@Slf4j
@Component
public class NewsListener implements ApplicationListener<NewsEvent> {@Overridepublic void onApplicationEvent(NewsEvent event) {log.info("消息监听器监听到消息,执行发送消息逻辑:"+event.getSource());}}

另一种是使用@EventListener注解,使用方式是直接在方法上添加该注解即可,具体实现如下:

@Slf4j
@Component
public class NewsListener  {@EventListener(NewsEvent.class)public void sendNews(){log.info("消息监听器监听到消息,执行发送消息逻辑");}}

控制层实现逻辑:

@RestController
@RequestMapping("/test")
public class TestController {@Autowiredprivate TestServiceImpl testService;@PostMapping("/applyCourse")public ResultVo applyCourse(){// 预约课程testService.applyCourse();return  ResultVoUtil.success();}
}

约课课程接口发送成功之后实现结果显示:

3.事件发布以及监听原理

凡事都讲究知其然知其所以然,对我们技术开发人员更是如此,思考几个问题。 事件发布者发送消息之后,监听器是如何立即接收到响应的呢?下面就从源码的角度看下执行原理: 实现类中执行发送事件逻辑,最终调用的是`AbstractApplicationContext`中的`publishEvent`,该方法的主要作用是将所给到的事件发送给所有的监听器.代码如下:

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {Assert.notNull(event, "Event must not be null");ApplicationEvent applicationEvent;// 省略部分代码// 利用事件发布器进行发布事件getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);// 省略部分代码}

继续看下事件发布的具体逻辑,SimpleApplicationEventMulticaster中的multicastEvent:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));Executor executor = getTaskExecutor();// 根据事件类型获取对应的事件监听器,根据是否配置线程池决定是异步多线程执行还是同步执行for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {if (executor != null) {// 线程池异步执行executor.execute(() -> invokeListener(listener, event));}else {// 同步执行invokeListener(listener, event);}}}

最终都是执行SimpleApplicationEventMulticasterdoInvokeListener,实现逻辑如下:

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {// 省略部分逻辑listener.onApplicationEvent(event);// 省略部分逻辑}

看到这里应该很明确了,这里就说明了为什么自定义的监听器需要实现ApplicationListener接口.
    以上是实现业务解耦采用事件监听的处理方式并对实现原理做了必要的分析说明,看到如果感觉有收获欢迎点赞收藏,另外也可以在评论区留言说下其他的业务解耦处理方式.

如何实现业务解耦?spring中事件监听了解一下相关推荐

  1. Spring之事件监听

    spring的监听事件模型应该是观察者模式.本人项目里的应用在process方法按日期同步某个库的数据,在方法最后publish一个event事件,这个事件用于后续同步过来的数据处理.事件处理采用了s ...

  2. Java中事件监听机制

    Java中事件监听机制 一.事件监听机制的定义 要想了解Java中的事件监听机制,首先就要去了解一下在Java中事件是怎样去定义的呢!在使用Java编写好一个界面后,我们就会对界面进行一些操作,比如, ...

  3. 框架源码专题:Spring的事件监听、发布机制 ApplicationListener

    文章目录 1.Spring内置事件 2.自定义事件 3.事件监听器 4.事件发布 publishEvent 4.Spring事件原理 5. 面试题:怎么样可以在所有Bean创建完后做扩展代码? 6. ...

  4. java中事件监听的实现

    一. 什么是监听事件 在程序执行过程中对某一个功能或者事件进行监听.例如,用户登录成功后,发送短信或者邮件信息给用户. 二.如何完成监听事件 监听事件是基于观察者模式实现的,要完成监听事件,需要准备好 ...

  5. html中事件监听的使用,Vue.JS入门篇--事件监听

    你可以使用 v-on 指令来绑定并监听 DOM 事件.绑定的内容可以是一个当前实例上的方法 (后面无需跟括号) 或一个内联表达式.如果提供的是一个方法,则原生的 DOM event 会被作为第一个参数 ...

  6. java中事件监听_Java中的事件监听机制

    鼠标事件监听机制的三个方面: 1.事件源对象: 事件源对象就是能够产生动作的对象.在Java语言中所有的容器组件和元素组件都是事件监听中的事件源对象.Java中根据事件的动作来区分不同的事件源对象,动 ...

  7. java中事件监听是什么意思_Java的事件监听器学习心得

    在Java的swing编程中,Java中的事件机制非常常用 一. 事件监听器的参与者: 1.事件对象: 一般继承自java.util.EventObject对象,由开发者自行定义. 2.事件源: 就是 ...

  8. vue中事件监听watch

    vue中的watch实际上是用来监听vue实例中的数据变化. 监听String <template><div @click="stringClick">{{ ...

  9. Spring中实现监听的方法

    在未使用框架进行编程的时候,我们常常在web.xml中加上这样一段话 <listener><listener-class>XXX</listener-class>& ...

最新文章

  1. easy-x库graphics.h图形库安装
  2. 《DB 查询分析器》中断SQL语句的执行
  3. redis 内存不足 排查_Redis 系统学习之 redis 内存模型
  4. 作者:司光亚(1967-),男,国防大学信息作战与指挥训练教研部教授,主要研究方向为战争复杂系统建模仿真。...
  5. C++实现MD5加密
  6. 成员/方法/属性/私有
  7. eoLinker-AMS接口管理系统
  8. moba寻路_MOBA代号105:道具收费 加入自动寻路等MMO元素
  9. 有趣的 Mysql 存储引擎 1
  10. Python 字典(Dictionary) items()方法
  11. unb计算机科学,【加拿大新布伦瑞克大学】加拿大UNB_University of New Brunswick - 加拿大大学 - 加拿大留学云...
  12. 手机上定时日程提醒怎么设置?
  13. oracle ndb,NDB语法 - ivaneeo's blog - BlogJava
  14. 短视频运营详解:抖音变现目前流行的是七种方式之一电商卖货
  15. 拿到外卖后秒退单,一连12天吃霸王餐的女子栽了!
  16. 边云协同的优点_边缘计算的云边协同
  17. AD中画圆弧形板框的方法
  18. 关于自然语言处理中的语义与概念
  19. 【网络协议模糊测试实战】使用sulley对PCManFTP进行模糊测试
  20. 【虚拟现实】基于Vizard的三维美术馆漫游

热门文章

  1. argus.py 可以仍是昔日素心悠游的少年
  2. 【电气专业知识问答】问:什么是交流不停电电源(UPS)?
  3. C语言学习笔记————code
  4. 利用易查分制作分班查询系统,怎么导入数据?
  5. 树梅派 网线和wifi 连接启用SSH 远程连接树梅派
  6. 邮件送达率低的六大症结
  7. Uncaught (in promise) 的解决方法
  8. 整理:部分银行核心系统的资料
  9. c语言单精度比大小,c语言单精度和双精度的区别.pdf
  10. 国内外一些开源项目,开源代码网站介绍