文章目录

  • pre
  • 事件监听机制的实现原理[观察者模式]
    • 事件 ApplicationEvent
    • 事件监听者 ApplicationEvent
    • 事件发布者 ApplicationEventMulticaster (多播器)
  • 工作流程
  • 源码解析
    • 初始化事件多播器 initApplicationEventMulticaster()
    • 注册事件到多播器中 registerListeners()
    • 事件发布publishEvent(默认同步)


pre

Spring5源码 - 10 Spring事件监听机制_应用篇

观察者模式

说了应用,那我们来看下Spring的源码是如何实现这种事件监听机制的吧


事件监听机制的实现原理[观察者模式]

其实就是观察者模式


事件 ApplicationEvent

事件监听者 ApplicationEvent

相当于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应逻辑


事件发布者 ApplicationEventMulticaster (多播器)

相当于观察者模式中的被观察者/主题, 负责通知观察者 对外提供发布事件和增删事件监听器的接口,维护事件和事件监听器之间的映射关系,并在事件发生时负责通知相关监听器


工作流程

Spring事件机制是观察者模式的一种实现,但是除了发布者和监听者者两个角色之外,还有一个EventMultiCaster的角色负责把事件转发给监听者。

AnnotationConfigApplicationContext#publishEvent(ApplicationEvent event)将事件发送给了EventMultiCaster, 而后由EventMultiCaster注册着所有的Listener,然后根据事件类型决定转发给那个Listener。


源码解析

debug走起,

Spring在ApplicationContext接口的抽象实现类AbstractApplicationContext中完成了事件体系的搭建。
AbstractApplicationContext拥有一个applicationEventMulticaster成员变量,applicationEventMulticaster提供了容器监听器的注册表。

还是进入到refresh方法中

refresh() -----> 直接看 initApplicationEventMulticaster() -----------> registerListeners() ---------> finishRefresh() 进入 ----> publishEvent(new ContextRefreshedEvent(this))


初始化事件多播器 initApplicationEventMulticaster()

protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();//判断IOC容器中包含applicationEventMulticaster 事件多播器的Bean的nameif (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {/创建一个applicationEventMulticaster的bean放在IOC 容器中,bean的name 为applicationEventMulticasterthis.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isDebugEnabled()) {logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else { //容器中不包含一个beanName 为applicationEventMulticaster的多播器组件//创建一个SimpleApplicationEventMulticaster 多播器this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);//注册到容器中beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isDebugEnabled()) {logger.debug("Unable to locate ApplicationEventMulticaster with name '" +APPLICATION_EVENT_MULTICASTER_BEAN_NAME +"': using default [" + this.applicationEventMulticaster + "]");}}}​

一句话概括:我们可以在配置文件中为容器定义一个自定义的事件广播器,只要实现ApplicationEventMulticaster就可以了,Spring会通过 反射的机制将其注册成容器的事件广播器,如果没有找到配置的外部事件广播器,Spring默认使用 SimpleApplicationEventMulticaster作为事件广播器


注册事件到多播器中 registerListeners()

protected void registerListeners() {//去容器中把applicationListener 捞取出来注册到多播器上去(系统的)for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}//开发人员实现了ApplicationListener 的组件String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}//在这里之前,我们早期想发布的事件 由于没有多播器没有发布,在这里我们总算有了自己的多播器,可以在这里发布早期堆积的事件了. (早起发布事件,会自动发布,无需调用pubilish)Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (earlyEventsToProcess != null) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}

一句话概括 : Spring根据反射机制,使用ListableBeanFactory的getBeansOfType方法,从BeanDefinitionRegistry中找出所有实现 org.springframework.context.ApplicationListener的Bean,将它们注册为容器的事件监听器,实际的操作就是将其添加到事件广播器所提供的监听器注册表中。


事件发布publishEvent(默认同步)

org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType)

进入 org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)

public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));//获取到所有的监听器for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {//看spring 容器中是否支持线程池 异步发送事件Executor executor = getTaskExecutor();if (executor != null) {executor.execute(new Runnable() {@Overridepublic void run() {invokeListener(listener, event);}});}else {  //同步发送事件invokeListener(listener, event);}}}

支持异步,默认同步 。

遍历注册的每个监听器,并启动来调用每个监听器的onApplicationEvent方法。由于SimpleApplicationEventMulticastertaskExecutor的实现类是SyncTaskExecutor,因此,事件监听器对事件的处理,是同步进行的。

来看看

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {//调用对于listener的onApplicationEvent事件listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isDebugEnabled()) {logger.debug("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

就是调用 listener.onApplicationEvent(event);


Spring5源码 - 11 Spring事件监听机制_源码篇相关推荐

  1. Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析

    文章目录 Pre 概览 开天辟地的时候初始化的处理器 @EventListener EventListenerMethodProcessor afterSingletonsInstantiated 小 ...

  2. Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析

    文章目录 Pre 实现原理 应用 配置类 Event事件 事件监听 EventListener 发布事件 publishEvent 源码解析 (反推) Spring默认的事件广播器 SimpleApp ...

  3. Spring5源码 - 10 Spring事件监听机制_应用篇

    文章目录 Spring事件概览 事件 自定义事件 事件监听器 基于接口 基于注解 事件广播器 Spring事件概览 Spring事件体系包括三个组件:事件,事件监听器,事件广播器 事件 Spring的 ...

  4. spring 扫描所有_自定义Spring事件监听机制

    开头提醒一下大家: 尽管我简化了Spring源码搞了个精简版的Spring事件机制,但是没接触过Spring源码的朋友阅读起来还是有很大难度,请复制代码到本地,边Debug边看 既然要简化代码,所以不 ...

  5. Springboot事件监听机制:工作原理

    目录 前言 1.观察者模式 1.1观察者模式的核心元素 1.2观察者模式的工作流程 2.springboot事件监听机制的基本工作原理 2.1事件发布器是什么时候在哪里产生的呢? 2.2事件监听器是什 ...

  6. spring 事件监听

    用一个简单的例子来实现spring事件监听的功能 这个例子主要功能是,记录那些用户是第一次登入系统,如果用户是第一次登入系统,则调用spring的事件监听,记录这些用户. 主要用到的spring的类和 ...

  7. spring中的事件监听机制

    Spring event listener 介绍 example 简单原理解释 自定义事件.监听和发布 事件 监听器 发布者 测试 更加一般的事件 @EventListener原理 介绍 exampl ...

  8. Spring容器的事件监听机制(简单明了的介绍)

    文章目录 前言 事件 1. 定义事件 2. 定义监听器 3. 定义发布器 Spring容器的事件监听机制 1.事件的继承类图 监听器的继承类图 总结 前言 上一篇我们介绍了SpringFactorie ...

  9. Spring事件监听原理

    1 简述Spring的生命周期 不论是Spring的监听机制原理还是Spring AOP的原理,都是依托于Spring的生命周期,所以要了解Spring的监听机制原理就需要先了解Spring的生命周期 ...

最新文章

  1. UVA11248 网络扩容(枚举割边扩充)
  2. c++的引用是什么意思?怎么回事?
  3. 去掉“3_人民日报语料”中每行前边的数字编号,改成“1, 2,......”
  4. android--service之aidl传递复杂对象,Android--Service之AIDL传递复杂对象
  5. python怎么调用方法_python中怎么调用自己的方法
  6. 怎么查询房贷批下来没?
  7. 基于云端的通用权限管理系统,SAAS服务,基于SAAS的权限管理,基于SAAS的单点登录SSO,企业单点登录,企业系统监控,企业授权认证中心...
  8. Python多行字符串
  9. 苹果电脑 默认安装jdk位置_CH01_JDK安装和配置(含macOS)
  10. 6 大神器在手,难怪是无敌的
  11. Python+Tushare股票数据分析
  12. Java蓝桥模拟战——特殊的数字:153是一个非常特殊的数,它等于它的每位数字的立方和,即153=1*1*1+5*5*5+3*3*3。编程求所有满足这种条件的三位十进制数。
  13. Arctime——可视化字幕编辑器,解放你的双手
  14. 今日头条前端面试总结
  15. JAVA 面向对象和集合知识点总结
  16. 西瓜视频直播助手下载与安装过程 0523
  17. ZooKeeper知识点整理
  18. html做图片模糊效果,CSS3 filter(滤镜) 制作图片高斯模糊无需JS
  19. hksi paper 1 香港证券资格考试卷一 备考经验分享(2022.10) 證券及期貨從業員資格考試
  20. Python与Excel——Xlwings基础操作

热门文章

  1. 微信广告服务器地址,【微信广告服务商平台】微信广告服务商平台运营经验分享!...
  2. android 之Dialog对话框(简易版)
  3. svn: Can't convert string from 'UTF-8' to native encoding
  4. tensorflow 制定 CPU 或GPU
  5. python 面向对象(三)多继承
  6. 116. Leetcode 1143. 最长公共子序列 (动态规划-子序列问题)
  7. 86. Leetcode 264. 丑数 II (动态规划-基础题)
  8. 定位系列论文阅读-RoNIN(二)-Robust Neural Inertial Navigation in the Wild: Benchmark, Evaluations
  9. tableau可视化数据分析60讲(二)-tableau入门篇之各模块功能介绍
  10. 强化学习(十)Double DQN (DDQN)