spring源码分析-ApplicationContext----扩展组件event listener

        我们知道 spring中的ApplicationContext在beanFactory(提供基础bean处理)基础上增加了扩展组件,例如国际化,资源,发布事件和监听事件,今天主要针对发布和监听事件做一次源码分析,看到底发布和监听是如何实现的?是否放队列消费 还是直接调用?

        核心代码如下

SimpleApplicationEventMulticaster中的multicastEvent方法 广播事件,从对应监听器set集合中遍历,取出对应监听器并直接调用监听器中的方法,整个大的过程包括

1.先实例化监听器并放到set集合中,

2.将发布事件存入到set集合中,

3.在spring调用refresh方法之后进行调用广播事件方法,其实是直接调用的监听器中的对应方法。

AbstractApplicationContext的注册监听器方法 将标注为@EventListener的类添加到set集合中。

调用步骤在spring加载bean的refresh方法之后,如下图

 

         可以看到循环是从getApplicationListeners()方法中获取的set集合,那这个集合又是哪里存的呢?点开getApplicationListeners()方法后的set集合 继续点击发现是如下方法存的值

 而这个方法又是在如下步骤被调用的,从refresh之后调用监听可以得知 这个set过程一定是在此之前的,可以详细看下这里的入口又是哪里。

这个方法在一开始先查找需要进行AOP处理的类名称和类类型,且类类型是实现了EventListener的。

之后拿到这些标注了EventListener注解的类进行调用以上处理监听具体内容的方法。这里重点要看

AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));

这个方法 是查询方法上标注了注解为EventListener.class的类,找到了注解所标注的类,就可以知道哪些监听器需要处理,然后调用监听器处理方法时,只需要将set集合中保存的事件内容传递即可(监听方法入参)。

是实例化的时候调用的 那么这类的实例化又是哪里调用的?请看bean加载的生命周期,如下

a、创建一个beanDefinitionNames的副本,用于后面循环初始化bean对象;

b、循环前一步骤的beanNames副本,挨个触发非懒加载、单例bean的初始化;

c、首先初始化的前提是bean不是抽象类、非懒加载的、并且是单例的;接着会判断bean是否实现了FactoryBean接口,如果bean实现了FactoryBean接口,那么通过getBean(&beanName)获取的是FactoryBean对象本身。再然后判断bean是否急切需要初始化,如果需要急切初始化,则会直接调用getBean方法初始化;

d、如果没有实现FactoryBean接口的bean,则执行普通的getBean逻辑;

e、最后,如果bean实例singletonInstance实现了SmartInitializingSingleton接口,则执行后初始化回调方法afterSingletonsInstantiated();

重点在最后的bean实例执行完初始化(变量赋值完成)之后进行回调。这里要注意是所有的加载到spring容器中的bean都会调用 不过上面的分析中会查看哪个类的方法包含EventListener注解,所以相当于执行回调的过程中检查了对应注解 进行处理。

整体流程就是如此

主要分为两块

1.在类初始化完成后回调过程中 去发现方法中标注了EventListener注解的类,找到之后放到set集合中。

2.在refresh方法调用完之后调用监听器的处理时,从刚才的set集合中取出监听器进行处理,处理过程中当然也需要拿出event进行传递,event对象在发布事件的时候已经存到一个set集合中。

分析的略有些杂乱,但是顺着代码看就会感觉很简单,大家批评指教!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【性能工程】性能比较:REST vs gRPC vs 异步通信

微服务之间的通信方式对微服务架构内的各种软件质量因素有重大影响(有关微服务网络内通信的关键作用的更多信息)。沟通方式会影响软件的性能和效率等功能性需求,以及可变性、可扩展性和可维护性等非功能性需求。因此,有必要考虑不…

宝塔Panel搭建Python环境

服务器安装python环境 找到软件商店 应用搜索 输入:python 安装Python项目管理器2.4 开启首页显示 回到首页 找到python管理器并点击进入 安装对应的python版本 到这里 服务器就可以告一段落了 在本地开发服务端应用并上传服务器 将写好的python应用 导出依赖…

pytorch学习指南

安装anaconda: https://blog.csdn.net/fan18317517352/article/details/123035625 教程:bilibili up主:一只小土堆 构建pytorch空间 pytorch安装 查看cpu 安装命令pytorch:conda install pytorch torchvision torchaudio cpu…

六大排序——(插入、希尔、选择、交换、归并、计数)

目录 一、插入排序 二、希尔排序 三、选择排序 1)直接选择排序: 2)堆排序 四、交换排序 1)冒泡排序 2)快速排序 1、Hoare版 2、挖坑法 3、前后指针 快排优化 快速排序非递归来实现 快排总结 五、归并排…

OpenCV转换HDR图像与源码分析

我们常见的图像位深一般是8bit,颜色范围[0, 255],称为标准动态范围SDR(Standard Dynamic Range)。SDR的颜色值有限,如果要图像色彩更鲜艳,那么就需要10bit,甚至12bit,称为高动态范围HDR(High Dynamic Range…

Access-Control-Allow-Origin跨域解决及详细介绍

重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。 首先,跨域不是问题。是一种安全机制。 这是你在开发时、上线前就必须提前考虑到的安全问题并且采取合适的手段去避免这个问题带来的程序错误。不过通常情况…

零拷贝详解

目录 一、什么是零拷贝 二、传统的IO执行流程 三、零拷贝相关的知识点回顾 1、内核空间&用户空间 2、用户态&内核态 3、上下文切换 4、虚拟内存 5、DMA技术 四、零拷贝实现的几种方式 1、mmapwrite实现的零拷贝 2、sendfile实现的零拷贝 3、sendfileDMA sc…

【若依】框架搭建,前端向后端如何发送请求,验证码的实现

若依框架 若依框架(Ruoyi)是一款基于Spring Boot和Spring Cloud的开源快速开发平台。它提供了一系列的基础功能和通用组件,能够帮助开发者快速构建企业级应用。若依框架采用了模块化的设计理念,用户可以选择需要的功能模块进行集…

STM32中static和extern的用法

static: A. static变量 称为静态变量。根据变量的类型可以分为静态局部变量和静态全程变量。 1. 静态局部变量 它与局部变量的区别在于: 在函数退出时, 这个变量始终存在, 但不能被其它 函数使用, 当再次进入该函数时, 将保存上次的结果。其它与局部变量一样。…

观察级水下机器人第一次使用总结2023年6月

最近有个科研项目需要用到ROV,其合同三年之前就签订了,由于疫情的影响,一直没有执行。刚好我们的ROV也验收了,正好派上用场。因为属于ROV使用的菜鸟级,我们邀请厂家无锡智海张工和陈工,中海辉固ROV操作经验…

合理组织安卓活动

本文所有代码均存放于https://github.com/MADMAX110/Starbuzz 开始构建一个应用时,你会考虑这个应用要包含什么,会有各种各样的很多想法,如何组织这些想法来建立一个直观、清晰的应用。 一、活动归类 要组织各种各样的活动,有一种…

详解Ribbon

目录 1.概述 2.使用 2.1.引入 2.2.启用 2.3.切换负载均衡算法 3.负载均衡源码分析 3.1.接口 3.2.抽象类 3.3.选择服务器 3.4.原子性 4.自定义负载均衡算法 1.概述 Ribbon是Netflix开源的一个客户端负载均衡库,也是Spring Cloud Netflix项目的核心组件之…