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. Java如何按空格读取内容

    String s = input.nextLine(); String[] data = s.split(" ");

  2. iOS常用算法

    1.冒泡排序 冒泡算法是一种基础的排序算法,这种算法会重复的比较数组中相邻的两个元素,如果一个元素比另一个元素大/小,那么就交换这两个元素的位置.重复一直比较到最后一个元素. 1.最差时间复杂度:O( ...

  3. 高分一号计算NDVI

    1.准备工作 如果想要ENVI友好一点,请下载ENVI5.3,并且安装China satellites 补丁(参考博客:ENVI扩展工具:中国国产卫星支持工具) App Store for ENVI下 ...

  4. 面试中linux常见的20个命令

    1.查找文件 find / -name filename.txt 根据名称查找/目录下的filename.txt文件. 2.查看一个程序是否运行 ps –ef|grep tomcat 查看所有有关to ...

  5. java同步和互斥【用具体程序说明】

    java同步和互斥[用具体程序说明]            所有对象都自动含有单一的锁,也就是所有对象都有且只有唯一的锁,所以当某个任务(线程)访问一个类A中含有sycnhronized的方法是,那么 ...

  6. javascript中的Date对象

    Date是什么? Date是日期类的构造函数 也是个对象,用于构造日期对象的实例. 有一个 now()方法,返回截止目前的时间戳(1970.1.1日始). Date.parse()接受 一定格式的日期 ...

  7. 使用Python画一个带坐标轴的圆

    Download Microsoft Visual Studio Microsoft Visual Studio enables you develop your python Application ...

  8. Anaconda安装(Windows)

    Anaconda集成了python和各种常用工具. 目前有两个版本,分别包含了python2.7和python3.5,并且自动添加环境变量.去官网下载安装包. 1.安装其他模块.conda insta ...

  9. KeyguardSliceView.java

    /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Versi ...

  10. Bartender标签传参与打印

    在VS中添加bartender的COM组件引用后(一定要添加,否则会提示找不到BarTender.Application): /// <summary> /// Bartender模板打印 ...