| |
|
开发:
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集合中,所以,小伙伴们,这就能解释清楚了,好,一切搞定,收工!!!!!!!!! ? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |