人人都能看懂的Spring源码解析,spring的事件监听机制

news2025/1/15 19:41:03

人人都能看懂的Spring源码解析,spring的事件监听机制

  • 原理解析
    • 事件监听机制
    • ApplicationEventPublisher、ApplicationEventMulticaster、ApplicationEvent、ApplicationListener
    • AbstractApplicationContext发布的事件类型
  • 代码走读
  • 总结

往期文章:

  1. 人人都能看懂的Spring底层原理,看完绝对不会懵逼
  2. 简单易懂的Spring扩展点详细解析,看不懂你来打我
  3. 人人都能看懂的Spring源码解析,配置解析与BeanDefinition加载注册
  4. 简单易懂又非常牛逼的Spring源码解析,ConfigurationClassPostProcessor的具体逻辑
  5. 简单易懂值得收藏的Spring源码解析,依赖注入和bean的初始化
  6. 人人都能看懂的Spring源码解析,Spring如何解决循环依赖
  7. 人人都能看懂的Spring源码解析,Spring如何处理AOP
  8. 人人都能看懂的Spring源码解析,Spring声明式事务是如何实现的
  9. 人人都能看懂的Spring源码解析,Spring声明式事务关于传播特性、事务挂起与恢复的处理

原理解析

事件监听机制

事件监听机制是观察者模式的一种实现方式,观察者模式里面一般有事件发布器、事件、事件监听器三个组件。事件监听器往事件发布器里面注册,事件发布器保存注册进来的事件监听器,一旦发生状态的变化,事件发布器向保存的事件监听器发布事件,通知事件监听器处理。

在这里插入图片描述

ApplicationEventPublisher、ApplicationEventMulticaster、ApplicationEvent、ApplicationListener

Spring中的ApplicationEventPublisherApplicationEventApplicationListener,分别对应事件监听机制中的事件发布器、事件、事件监听器。而ApplicationEventMulticaster是事件广播器,被ApplicationEventPublisher持有,用于广播发布的事件给各个ApplicationListener。

在这里插入图片描述

ApplicationEventPublisher接口有一个抽象方法 void publishEvent(Object event) ,用于发布事件。

ApplicationEventMulticaster接口的抽象方法 void multicastEvent(ApplicationEvent event),用于广播事件。

ApplicationListener接口有一个抽象方法 void onApplicationEvent(E event) ,用于接收事件通知。

在这里插入图片描述

AbstractApplicationContext实现了ApplicationEventPublisher接口,用一个 Set<ApplicationListener<?>> 类型的变量 applicationListeners 保存注册进来的ApplicationListener。

在这里插入图片描述

AbstractApplicationContext有一个 void addApplicationListener(ApplicationListener<?> listener) 方法接收注册进来的ApplicationListener,然后保存到applicationListeners中。然后会调用ApplicationEventMulticaster的addApplicationListener方法,把注册进来的ApplicationListener也保存到ApplicationEventMulticaster中。

在这里插入图片描述

ApplicationEvent继承了EventObject,EventObject创建时需要接收一个事件源source。事件源就是触发该事件的源头。

在这里插入图片描述

AbstractApplicationContext发布的事件类型

在这里插入图片描述

AbstractApplicationContext发布的事件类型一共四种:

  • ContextClosedEvent 上下文关闭事件
  • ContextRefreshedEvent 上下文刷新完成事件
  • ContextStartedEvent 上下文启动事件
  • ContextStoppedEvent 上下文停止事件

它们都继承 ApplicationContextEvent ,而ApplicationContextEvent又继承了ApplicationEvent。与Spring上下文状态变化相关的事件都继承ApplicationContextEvent,而ApplicationEvent类型的事件则范围更广。

其中 ContextRefreshedEvent 是我们最熟悉的事件类型,会在AbstractApplicationContext的 finishRefresh() 方法中发布,而finishRefresh()又会在 refresh() 方法调用完 finishBeanFactoryInitialization(beanFactory) 方法之后被调用,也就是说Spring会在初始化完所有非懒加载单例bean之后,会发布一个上线文刷新完成事件。

代码走读

在这里插入图片描述

我们启动Spring应用,AbstractApplicationContext的refresh() 方法就会被调用,refresh()方法用于刷新Spring应用上下文,创建并初始化Spring容器,refresh()方法会调用finishBeanFactoryInitialization(beanFactory)进行非懒加载单例bean的初始化,调用完 finishBeanFactoryInitialization(beanFactory) 方法之后,会调用finishRefresh()方法,Spring会在这个方法里面触发上下文刷新完成事件的发布。

在这里插入图片描述

finishRefresh()方法会以AbstractApplicationContext作为事件源创建一个ContextRefreshedEvent事件,并调用publishEvent方法发布该事件。

在这里插入图片描述

publishEvent方法里面会调用getApplicationEventMulticaster()方法获取到ApplicationEventMulticaster事件广播器,然后调用ApplicationEventMulticaster的multicastEvent方法广播ContextRefreshedEvent事件给所有注册进来的ApplicationListener。

在这里插入图片描述

进入到SimpleApplicationEventMulticaster的multicastEvent方法,里面会调用getApplicationListeners方法获取所有的ApplicationListener,遍历每一个ApplicationListener,调用invokeListener(listener, event)方法,listener就是当前遍历到的ApplicationListener,event就是ContextRefreshedEvent事件。

在这里插入图片描述
invokeListener方法调用doInvokeListener方法。

在这里插入图片描述
doInvokeListener方法就会调用ApplicationListener的onApplicationEvent方法,通知该ApplicationListener。

总结

以上就是对于spring的事件监听机制的讲解的全部内容。spring的事件监听机制算是Spring源码里面相对简单的一块,所以本篇文章的内容也不算多。下面就对spring的事件监听机制的讲解做一个总结。

  1. Spring事件监听机制中最重要的四个组件分表是ApplicationEventPublisher、ApplicationEventMulticaster、ApplicationEvent、ApplicationListener。
  2. ApplicationEventPublisher会持有ApplicationEventMulticaster。注册到ApplicationEventPublisher的ApplicationListener也会保存一份到ApplicationEventMulticaster;ApplicationEventPublisher发布的ApplicationEvent会被ApplicationEventMulticaster广播给注册进来的所有ApplicationListener。
  3. ContextRefreshedEvent事件是我们最熟悉的事件类型,会在AbstractApplicationContext的finishRefresh方法中发布,而finishRefresh方法又会在AbstractApplicationContext的refresh方法中完成所有非懒加载单例bean的初始化后被调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/679054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据Doris(四十八):Steam Load案例和注意事项

文章目录 Steam Load案例和注意事项 一、Steam Load案例 1、准备数据 2、创建 Doris 表 3、创建 Stream Load 导入任务 4、查看任务 5、查询Doris 表结果 二、注意事项 Steam Load案例和注意事项 一、Steam Load案例 下面以导入Linux节点本地磁盘数据到Doris为例&…

Python小游戏集合(开源、开源、免费下载)

Python小游戏集合 0. 前言1. 为什么用Python做游戏2. 小游戏集合及源代码&#xff08;整理不易&#xff0c;一键三连&#xff09;2.1 外星人小游戏2.2 塔防小游戏2.3 三国小游戏2.4 打飞机游戏2.5 飞机大战小游戏2.6 玛丽快跑小游戏2.7 涂鸦跳跃小游戏2.8 猜数字小游戏2.9 坦克…

金蝶云星空财务账套数据库中了.locked勒索病毒的解密步骤和预防方式

最近&#xff0c;金蝶云星空财务账套的数据库遭到了一次严重的勒索病毒攻击&#xff0c;导致数据库中重要数据被加密。这种攻击对企业来说是一种巨大的威胁&#xff0c;因为数据是企业的核心资产之一。而此次攻击的病毒为.locked后缀勒索病毒&#xff0c;而locked勒索病毒在本月…

VUE L 生命周期 ⑩①

目录 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ V u e j s Vuejs Vuejs初见生面周期分析生命周期生命周期总结总结 文章有误请指正&#xff0c;如果觉得对你有用&#xff0c;请点三连一波&#xff0c;蟹蟹支持✨ ⡖⠒⠒⠒⠤⢄…

Spring 项目过程及如何使用 Spring

文章目录 1.创建 Spring 项目步骤1.1 创建 Maven 项目1.2添加 Spring 框架支持1.3 添加启动项2.如何使用 Spring2.1 存储 Bean 对象2.1.1 创建 Bean对象2.1.2 将 Bean对象注册到容器中 2.2 获取并使用 Bean对象2.2.1 使用 ApplicationContext 获取对象2.2.2 使用 BeanFactory 获…

五、Docker镜像发布到阿里云/私有库

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 前言一、本地镜像发布到阿里云1.1 流程图1.2 注册阿里云创建容器服务个人实例1.3 创建命名空间1.4 创建镜像仓库1.5 将镜像推送到阿里云本地仓库 二、从阿里云仓库拉去自己推…

Matlab统计分析 -- 聚类算法模型

统计分析 – 聚类算法模型 距离分析 数据标准化 欧氏距离与量纲有关&#xff0c;因此&#xff0c;有时需要对数据进行预处理&#xff0c; 如标准化等。 在MATLAB中的命令是zscore&#xff0c;调用格式 Z zscore(X) 输入X表示N行p列的原始观测矩阵&#xff0c;行为个体&…

Nginx-反向代理详解

本文已收录于专栏 《中间件合集》 目录 概念说明什么是Nginx什么是反向代理 功能介绍配置过程1.修改nginx配置文件修改全局模块修改工作模块修改HTTP模块 2.保存配置文件3.重启配置文件4.查看配置文件是否重启成功 配置反向代理的好处总结提升 概念说明 什么是Nginx Nginx 是一…

你真的会写 HelloWorld 吗?

目录 Hello World 写一个批处理命令行脚本 关于include 关于程序的入口 输出充定向 在内存的存储详情 WinHex工具介绍 初学C语言时&#xff0c;第一个程序一定是Hello World!。但是Hello World的具体实现细节你真的了解吗&#xff1f; Hello World C语言代码如下&#…

SSM国内热门景点推荐系统的开发-计算机毕设 附源码83762

SSM国内热门景点推荐系统的开发 摘 要 为了方便用户快速定位自己感兴趣的国内热门旅游景点信息&#xff0c;国内热门景点推荐系统应运而生。本系统的前端界面主要实现页面的美观和动态效果使之符合广大群众的审美观&#xff0c;后台主要使用的技术主要有Java编程语言&#xff0…

Paragon NTFS2023Mac读取、写入外置移动硬盘软件

在我们日常使用电脑时常常会出现NTFS格式分区&#xff0c;那你知道NTFS For Mac是什么&#xff1f;简单的理解就是让你在mac系统下&#xff0c;可以正常读写Windows的Ntfs格式的分区。其中还包括Windows NT 4&#xff0c;2000&#xff0c;XP&#xff0c;2003&#xff0c;Vista&…

springboot 新农村信息化管理与服务平台-计算机毕设 附源码83372

springboot 新农村信息化管理与服务平台 目 录 摘要 1 绪论 1.1新农村信息化概念 1.2研究内容 1.3springboot框架介绍 1.4论文结构与章节安排 2 新农村信息化管理与服务平台系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 法律可行性分析…

如何用GitKeep提交和推送一个空目录或文件夹

目录 .Gitkeep简介 .Gitkeep是什么 如何用GitKeep提交和推送一个空目录或文件夹 结论 相关参考 .Gitkeep简介 Git是一个开发工具&#xff0c;帮助团队管理他们的源代码并有效地处理项目。通过GitHub或其他托管服务上传时&#xff0c;不可能包括空白/空目录。这是有问题的…

[Arduino] ESP32开发 - 基础入门与原理分析

实用 GPIO 用到再查&#xff0c;熟能生巧&#xff0c;别上来就背图&#xff0c;一天你就忘了&#xff01; 仅输入引脚 下面的四个引脚由于内部没有上拉下拉电阻&#xff0c;所以仅仅支持输入信号 GPIO 34 GPIO 35 GPIO 36 GPIO 39 SPI Flash 闪存引脚 这些引脚都是对 ESP32 内…

【Java】以数组为例简单理解引用类型变量

我们首先要知道内存是一段连续的存储空间&#xff0c;主要用来存储程序运行时数据的&#xff0c;如果对内存中存储的数据不加区分的随意存储&#xff0c;那对内存管理起来将会非常麻烦,就像一个杂乱的房间&#xff0c;你如果想在这个房间里找一个东西的话&#xff0c;找起来就会…

怎么使用Sprng提供的容器去注册一个Bean对象(BeanFactory工厂)

目录 BeanFactory怎么使用Sprng提供的容器去注册一个Bean对象&#xff08;BeanFactory工厂&#xff09;总结 BeanFactory 怎么使用Sprng提供的容器去注册一个Bean对象&#xff08;BeanFactory工厂&#xff09; 重点&#xff1a;Spring容器&#xff0c;例如Beanfactory其实并没…

人生还需搏一搏,规划指南不可缺

前言 如题我的人生还需要再搏一搏&#xff0c;本篇文章&#xff0c;我将整理指定下个人目标计划&#xff0c;让这篇文章去指引自己去指导自己前进。敲下这一行字想起了高中时期的一段经历&#xff0c;在高一时我准备了一个小本子&#xff0c;按高一到高三每年每学期的期中&…

KeeperErrorCode = NoAuth for /hbase/tokenauth/keys

kerberos配置hbase出現問題 環境如下&#xff1a; 问题描述 想要在hadoop ha的場景上&#xff0c;基於kerberos配置hbase ha&#xff0c;出現了如下的bug org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode NoAuth for /hbase/runningat org.apache.…

C++ 第四弹动态内存管理

目录 1. C/C程序内存划分 2. C语言中内存管理的方式 3. new /delete 和 new[]/delete[] 4. void* operator new(size_t size) 和 void operator delete(void*) 可以重载的 5. 定义为new表达式 6. 常见的面试题 1. C/C程序内存划分 1. 栈 又叫堆栈 -- 非静态局部变量 / 函数…

PHP代码审计之环境配置

PHP代码审计之环境配置 前言一、PHP环境配置1.1 phpstudy和phpstorm下载配置1.2 Xdebug 配置1.3 phpstudy 基本使用1.4 phpstorm基本使用1.5 RIPR下载使用 二、代码审计配置文件2.5 PHP的核心配置&#xff08;php.ini&#xff09;1. safe_mode2. magic_quote_gpc3. magic_quote…