SpringBoot启动源码探究---listeners.starting()
1.首先调用starting()方法,其内部是一个对所有listener的starting()调用的for循环,然后每个listener调用另一个starting方法,其内部调用multicastEvent方法,其又调用其他multicastEvent方法,其又继续调用其他的multicastEvent方法,然后在里面进行了这样的逻辑:先根据事件类型获取到合适的监听器,然后对这些合适的监听器遍历,每一个监听器都开启一个独立的线程去执行监听(具体放在下一节)

2.其中获取到合适的监听器很重要,如何匹配?
下述方法表示先从缓存中获取,如果没有再老老实实地检索合适的监听器,然后再将检索到的监听器放进缓存,最后返回监听器,这样做的好处是下次再用到相同的监听器,可以走捷径,很快.其中有一个核心方法:检索监听器

3.如何检索监听器?retrieveApplicationListener方法
该方法表示从两条途径检索合适的监听器:一条是从现有的监听器列表中检索,一条是从现有的监听器实例列表中检索.
但不管从哪里检索,它们的核心检索方法都是一样的--->判断是否支持该事件类型的supportsEvent()方法

4.supportsEvent()方法如何运作?
该方法表示当前遍历到的监听器必须同时支持事件类型和事件源类型,才能成为合适的监听器.核心方法是supportsEventType()和supportsSourceType().

5.supportsEventType()和supportsSourceType()两个方法看上去长的差不多,没错!它们的原理也差不多,都是两个字:"比较"看是否支持.所以我们只需要看supportsEventType就明白如何运作.
该方法有个if-else判断,两个分支的核心方法名字看上去还不一样,其实if中的supportsEventType()方法本质和else中的isAssignable()目的都一样,也就是名称不一样而已,核心还是两个字:"比较"

6.说了两次"比较"了,那什么是比较呢?
就是将方法指定的事件类型与传入的事件类型比较,如果前者是后者的超类,则合适,否则不合适,如下:一个例子

补充:此处的isAssignableFrom()方法已经到底了,是native方法,作用就是比较前者是否是后者的爹.
7.上面只是ConfigFileApplicationListener监听器中supportsEventType方法的实现,其实很多监听器都有自己的实现,每种监听器都在自己的实现中规定了自己感兴趣的事件类型和事件源类型,正因此,才能与传入的事件类型做比较,从而判断自己应不应该监听它.如下面这个监听器,其感兴趣的类型与上面不同:

8.说完了如何比较事件类型,也就说完了如何比较事件源类型,因为他们的原理完全一样,都是通过判断传入的类型是不是自己内定类型的子类/实现类,从而确定要不要监听它.
但是,不同的监听器都是调用同一个方法去比较的,如何做到的?这就是本源码分析中一个比较有意思的问题,答案是这里使用了面向接口编程
所有的监听器都实现了GnericApplicationListener,当真正的实例调用supportsEventType()方法时,它们只会调用到自己所在的实现类的方法,从而达到"和而不同".
9.以上浅见,感谢指正!
SpringBoot启动源码探究---listeners.starting()的更多相关文章
- SpringBoot启动源码探究----configureHeadlessProperty()方法
该方法只做了一件事:设置了一个名为java.awt.headless的系统属性,源码如下: private void configureHeadlessProperty() { System.setP ...
- SpringBoot启动源码探究---getRunListener()
该方法目的是获取SpringApplicationRunListener getRunListener()-----调用----> getSpringFactoriesInstances()-- ...
- SpringBoot启动源码及自定义starter
为什么springboot工程能够在mian方法中完成启动呢?需要大家掌握的有几个点:1.SPISPI在springboot中是去读取META-INF/spring.factories目录的配置文件内 ...
- Springboot启动源码详解
我们开发任何一个Spring Boot项目,都会用到如下的启动类 @SpringBootApplication public class Application { public static voi ...
- spring-boot-2.0.3启动源码篇二 - run方法(一)之SpringApplicationRunListener
前言 Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,争取不让大家每周的期望落空.一周之中可 ...
- spring-boot-2.0.3启动源码篇一 - SpringApplication构造方法
前言 spring-boot-2.0.3应用篇 - shiro集成,实现了spring-boot与shiro的整合,效果大家也看到了,工程确实集成了shiro的认证与授权功能.如果大家能正确搭建起来, ...
- spring-boot-2.0.3之quartz集成,数据源问题,源码探究
前言 开心一刻 着火了,他报警说:119吗,我家发生火灾了. 119问:在哪里? 他说:在我家. 119问:具体点. 他说:在我家的厨房里. 119问:我说你现在的位置. 他说:我趴在桌子底下. 11 ...
- SpringBoot读取配置文件源码探究
1. SpringBoot读取配置文件源码探究 1.1. 概览 springboot的源码是再原来的Spring源码上又包了一层,看过spring源码都知道,当我们从入口debug进去的时候,原来的S ...
- spring-boot-2.0.3启动源码篇四 - run方法(三)之createApplicationContext
前言 此系列是针对springboot的启动,旨在于和大家一起来看看springboot启动的过程中到底做了一些什么事.如果大家对springboot的源码有所研究,可以挑些自己感兴趣或者对自己有帮助 ...
随机推荐
- 小试牛刀 WiFi 远控 + wendu
废话 少说 直接上代码 DH11三根线 信号线 接2 WiFi 模块 r-------t t--------r en&vcc------3.3v 剩下的 共地的啦 double Fahre ...
- JS 最简单数组去重
,,,,])) // 再把set转变成array console.log(newArr) // [1,2,3,4]
- asp.net mvc global.asax文件详解
一.文件概述 global.asax这个文件包含全局应用程序事件的事件处理程序.它响应应用程序级别和会话级别事件的代码. 运行时, Global.asax 将被编译成一个动态生成的 .NET Fram ...
- Java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind异常
端口被占用,可能是其他程序占用,也有可能是自己代码逻辑不对,比如BZ在写SocketServer时把添加端口的代码放进了while里(sasasa.....). 查看本机端口是否被占用:netstat ...
- conts、var 、let的区别
1.const定义的变量不可以直接修改,通过 this.a = 'kkk' 进行修改, 而且必须初始化. 2.var定义的变量可以修改,如果不初始化会输出undefined 3.let是块级作用域,函 ...
- React Lifecycle
React Lifecycle 分为三种: 初始化阶段 状态的更新 销毁 实例化: ReactDom.render 用于将模板转换成HTML语言,并插入DOM节点. 1.getDefaultProps ...
- android studio连接真机大概问题
首先,确定手机Android的版本(最好用统一版本) 版本一样的话错误会少一点... 手机打开开发者选项(每个手机不同,百度可查) 开发者选项中打开USB调试 点击OK,可以进入Android mon ...
- SqlSugar ORM 的学习
http://www.codeisbug.com/Doc/8/1163 https://www.cnblogs.com/sunkaixuan/p/6082664.html
- install MariaDB 10.2 on Ubuntu 18
Here are the commands to run to install MariaDB 10.2 from the MariaDB repository on your Ubuntu syst ...
- 使用CMake生成解决方案后构建INSTALL报错
错误 1 error MSB3073: 命令“setlocal"D:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=Debug - ...