IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Springboot中ApplicationListener工作原理(源码) -> 正文阅读

[Java知识库]Springboot中ApplicationListener工作原理(源码)

一、启动参数

其中subMainClass为启动类,我的启动类是:

?二、源码

1、当springboot项目启动时,会进入run方法

?

?让我们进入第四步,看看里面都干了啥?

?接着跟进去,看看SpringFactoriesLoader.loadFactoryNames这个方法:

?其中factoryClassName:org.springframework.context.ApplicationListener,classLoader会去

META-INF/spring.factories中找ApplicationListener=XXXX这样的数据加载出来

?并把它放入result中返回,这其中有随便拿一个类出来打上断点,看看什么时候调用,比如:

?ClearCachesApplicationListener这个类,断点如下:

?从第六步中的方法:SpringFactoriesLoader.loadFactoryNames出来后,接着往下走,进入方法:

createSpringFactoriesInstances,

?其中,

type:interface org.springframework.context.ApplicationListener

parameterTypes:[]

classLoader:sun.misc.Launcher$AppClassLoader@14dad5dc

args:[]

names:从META-INF/spring.factories中获取的集合

这个方法的意思是,将所有names调用无参构造反射进行实例化,如下图所示:

?这个方法执行完成之后,就一直往上返回,返回到第四步,执行setListeners方法,

?

?就是将这个实例化的集合添加到到SpringApplication类的listeners属性中:

此时,第二步中的new SpringApplication(sources)已经走完,接着看看run(args)方法,

?跟着2-1往里面走:

?让我们先看2-2中的方法:getSpringFactoriesInstances,其中:

this:org.springframework.boot.SpringApplication@10feca44

args:[config.server=192.168.2.155:2181, config.auth=123456, config.namespace=dev, config.appid=ms.roster.weizhi] 就是我的启动入参

让我们接着看2-3中的方法做了些什么,其中SpringFactoriesLoader.loadFactoryNames是不是很眼熟,就是从META-INF/spring.factories获取了key为org.springframework.boot.SpringApplicationRunListener的数据集:

?然后,调用createSpringFactoriesInstances方法进行反射实例化,调用的有参构造:

?其实就是调用类EventPublishingRunListener中的有参构造:

?接着我们来看看这个构造参数,实例化了类:SimpleApplicationEventMulticaster,遍历application.getListeners(),其实就是?:

?这步中的listeners,拿到的就是:

这里面的实例对象,让我们接着来看,将遍历后的listener放入initialMulticaster中:

this.initialMulticaster.addApplicationListener(listener);

?其实是将listener最终放在了ListenerRetriever的applicationListeners中,其中SimpleApplicationEventMulticaster是继承AbstractApplicationEventMulticaster类

?也就是说,最终将所有的ApplicationListener都放入了类ListenerRetriever的属性applicationListeners中,此处也是重点。

那么接着就会从2-3返回,结果如下:

?这个就是2-2中getSpringFactoriesInstances执行完的结果,接着执行方法:new SpringApplicationRunListeners方法:将结果集装入org.springframework.boot.SpringApplicationRunListeners.listeners中,那么就是:

SpringApplicationRunListeners装有SpringApplicationRunListener实现类的结果集,SpringApplicationRunListener实现类中装有ApplicationListener实现类的结果集,这样一层一层包装也就是说:

?那么,执行完之后一层一层往上返回,到达2-1中,接着往下执行方法:listeners.starting();

?跟进去看看:

?将listeners中的SpringApplicationRunListener拿出来遍历,接着跟进去:listener.starting(),就是EventPublishingRunListener中的方法:

?其中:this.application, this.args就是前面2-4中传入的SpringApplication实例和启动入参,封装进类ApplicationStartedEvent中,并将ApplicationStartedEvent传入方法:

this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));

?

?让我们接着看2-10中的方法:getApplicationListeners

其实2-11中的source就是?this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));方法中的this.application

跟着2-12这个重要的方法往里面走:

2-13的这个取值是不是很熟悉,就是从2-6中的取得集合,然后往上返回,返回到2-10中,进行遍历,执行方法:invokeListener

?说白了,就是循环执行每一个ApplicationListener实现类的方法:onApplicationEvent,那么让我们最终看看上面打了断点的类:ClearCachesApplicationListener是不是就会被执行了:

?最终完美被拿捏,哈哈哈哈哈~~~~

但是!!!!!!

经过我仔细的调试,发现ClearCachesApplicationListener中的方法并不是在listeners.starting()中执行的,难道是哪儿出了问题,那就让我们仅需深入的看看

?让我们重新进到2-12里面:

发现返回值竟然只有5个,如下:

?其中并没有ClearCachesApplicationListener,不要着急,我们在往上找找,进入方法:retrieveApplicationListeners,也就是2-13,发现ClearCachesApplicationListener还存在,接着往下走,以为最终这个方法返回的是allListeners,结果这儿allListeners中就已经只剩5个实例了,那么问题一定是出在这儿,让我们仔细瞅瞅:

?发现这个方法:supportsEvent很可疑,那么我们就来看看这个方法到底做了啥吧?

?外层for循环到了类ClearCachesApplicationListener,我们发现,listener instanceof GenericApplicationListener=false,那么就要走new GenericApplicationListenerAdapter(listener)这段逻辑,最终我们发现,它将EventType进行了解析:

?然后接着往下走,我们就发现:

那么,就没有必要往下看了,因为?ClearCachesApplicationListener类中的EventType为ContextRefreshedEvent,而非ApplicationStartedEvent,所以直接返回false,那么在2-17中自然就不会被add到allListeners集合中,所以,小伙伴们,这就能解释清楚了,好,一切搞定,收工!!!!!!!!!

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-15 18:08:21  更:2021-12-15 18:10:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:55:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码