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()的更多相关文章

  1. SpringBoot启动源码探究----configureHeadlessProperty()方法

    该方法只做了一件事:设置了一个名为java.awt.headless的系统属性,源码如下: private void configureHeadlessProperty() { System.setP ...

  2. SpringBoot启动源码探究---getRunListener()

    该方法目的是获取SpringApplicationRunListener getRunListener()-----调用----> getSpringFactoriesInstances()-- ...

  3. SpringBoot启动源码及自定义starter

    为什么springboot工程能够在mian方法中完成启动呢?需要大家掌握的有几个点:1.SPISPI在springboot中是去读取META-INF/spring.factories目录的配置文件内 ...

  4. Springboot启动源码详解

    我们开发任何一个Spring Boot项目,都会用到如下的启动类 @SpringBootApplication public class Application { public static voi ...

  5. spring-boot-2.0.3启动源码篇二 - run方法(一)之SpringApplicationRunListener

    前言 Springboot启动源码系列还只写了一篇,已经过去一周,又到了每周一更的时间了(是不是很熟悉?),大家有没有很期待了?我会尽量保证启动源码系列每周一更,争取不让大家每周的期望落空.一周之中可 ...

  6. spring-boot-2.0.3启动源码篇一 - SpringApplication构造方法

    前言 spring-boot-2.0.3应用篇 - shiro集成,实现了spring-boot与shiro的整合,效果大家也看到了,工程确实集成了shiro的认证与授权功能.如果大家能正确搭建起来, ...

  7. spring-boot-2.0.3之quartz集成,数据源问题,源码探究

    前言 开心一刻 着火了,他报警说:119吗,我家发生火灾了. 119问:在哪里? 他说:在我家. 119问:具体点. 他说:在我家的厨房里. 119问:我说你现在的位置. 他说:我趴在桌子底下. 11 ...

  8. SpringBoot读取配置文件源码探究

    1. SpringBoot读取配置文件源码探究 1.1. 概览 springboot的源码是再原来的Spring源码上又包了一层,看过spring源码都知道,当我们从入口debug进去的时候,原来的S ...

  9. spring-boot-2.0.3启动源码篇四 - run方法(三)之createApplicationContext

    前言 此系列是针对springboot的启动,旨在于和大家一起来看看springboot启动的过程中到底做了一些什么事.如果大家对springboot的源码有所研究,可以挑些自己感兴趣或者对自己有帮助 ...

随机推荐

  1. Sublime Text 3利用Snippet创建Getter和Setter

    1. Tools -> Developer -> New Snippet. 2. 复制以下内容并保存: <snippet> <content><![CDATA ...

  2. java编码与解码(一)

    转:https://blog.csdn.net/heyanxi0101/article/details/80356870 java编码与解码(一) 编码表概述和常见的编码表 概述:有字符及其对应的数值 ...

  3. C语言进阶1-#define和const

    宏的命名规范:一般以项目前缀开头,key结尾. #开头表编译. 宏的用法:1.定义常用字符串. 2.定义一段代码. const与宏的区别:1.编译时刻:宏-预编译    const-command+b ...

  4. ---————for循环打印爱心

    //打印爱心public class Xin{ public static void main (String [] args){ for(int i=1;i<=4;i++){ for(int ...

  5. format() expandtabs() 输入表格数据

    1 输入表格数据 format(self, *args, **kwargs): # known special case of str.format """ S.form ...

  6. git教程:删除文件

    在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交: $ git add test.txt $ git commit -m "add test. ...

  7. yii2.0 curd操作

    $customer=new Customer();//插入操作 $customer->name='小熊'; $customer->save(); //修改操作 $model=Custome ...

  8. thinkphp5.0引入类

    /application/index/controller/Test.php <?php namespace app\index\controller; 当前命名空间名称 use think\C ...

  9. django如何查看mysql已有数据库中已有表格

    首先正常创建django项目,配虚拟环境,改配置文件,正常创建models,创建迁移和启动迁移等 接着通过找到Terminal窗户,双击,打开窗口 输入命令 python manage.py in i ...

  10. mysql _触发器

    MySQL 触发器 MySQL包含对触发器的支持.触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行. 1.创建触发器在MySQL ...