springboot2.x初探(二)

这篇文章接着 springboot2.x初探(一)

springboot2.x初探(二)_第1张图片

上篇文章中我们对 1 处的代码进行了分析,这篇文章来继续分析 2 处的代码:

springboot2.x初探(二)_第2张图片

springboot2.x初探(二)_第3张图片

由于这个方法比较长所以截了两个图,下面我们就按照截图中步骤的编号来一个一个看。

我们先来看看 1 处的StopWatch是什么

springboot2.x初探(二)_第4张图片

从类上的注释可以知道,这就是一个简单的记录开始时间和结束时间的功能的封装,它是非线程安全的。它的start 方法如下:

springboot2.x初探(二)_第5张图片

可以看到就是记录了一个任务名字为空的任务的开始时间。

4处的 SpringBootExceptionReporter:

springboot2.x初探(二)_第6张图片

它就是应用启动过程中发生错误的时候给用户抛出异常用的。

5 处的配置 java.awt.headless 属性的值,默认为 true

这个  java.awt.headless 是做什么用的呢?查到了一篇这样的博客:

https://blog.csdn.net/wodeyuer125/article/details/50502914

springboot2.x初探(二)_第7张图片

6 处的监听器:

springboot2.x初探(二)_第8张图片

它是SpringApplication 的run方法的监听器。

springboot2.x初探(二)_第9张图片

它的 starting方法会在run方法开始的时候马上调用。

通过 getRunListeners方法获取 SpringApplicationRunListener类的实现类的实例:

springboot2.x初探(二)_第10张图片

看一个listener实现类:

7处的starting

springboot2.x初探(二)_第11张图片

这里的 initialMulticaster :

先看看这个 SpringApplicationRunListener的实现类:

springboot2.x初探(二)_第12张图片

它使用一个内部的广播器来在context刷新之前发布触发的事件。

springboot2.x初探(二)_第13张图片

它就是将事件广播给所有注册的监听器,让监听器忽略不感兴趣的事件。

具体的广播方法在SimpleApplicationEventMulticaster类中,如下:

springboot2.x初探(二)_第14张图片

可以看到每个listener都使用了一个executor来调用,其中调用了一个 resolveDefaultEventType的方法,

springboot2.x初探(二)_第15张图片

这里有个判断判断传入的参数是不是 ResolvableTypeProvider的实例,我们上面实例化的是一个ApplicationStartingEvent:

springboot2.x初探(二)_第16张图片

我们看看这个ApplicationStartingEvent是不是实现了ResolvableTypeProvider接口:

这个过程中可以发现这个ApplicationStartingEvent就是对SpringApplication和参数的一个封装,同时很明显,它没有实现ResolvableTypeProvider接口,所以在 forInstance方法中调用的是:

接着看这个 forClass是怎么回事:

springboot2.x初探(二)_第17张图片

为传入的类返回了一个 ResolvableType,

springboot2.x初探(二)_第18张图片

可以看到这个 ResolvableType就是记录传入的类的类型,这个类型做什么用呢?

springboot2.x初探(二)_第19张图片

它在 getApplicationListeners方法中被调用了:

springboot2.x初探(二)_第20张图片

springboot2.x初探(二)_第21张图片

其中的ListenerCacheKey:

springboot2.x初探(二)_第22张图片

这里看到ListenerCacheKey竟然是一个Map的key,它是一个对象但是作为一个key了,那么它肯定重写了 hashcode和equals方法,我们看看:

springboot2.x初探(二)_第23张图片

果然如此,这里面具体的内容不在今天分析范围。接着往下看:

springboot2.x初探(二)_第24张图片

这个ListenerRetriever是一个私有的内部类,

springboot2.x初探(二)_第25张图片

看到这里的时候就有个疑问这个 ListenerRetriever中的applicationListeners是什么时候赋值的?

然后想到了之前的获取runlisteners方法中有获取实例化的runlisteners,看到了其中的types就是构造函数的参数类型,然后把它自己(SpringApplication)和args参数传了进去。

springboot2.x初探(二)_第26张图片

然后看到

springboot2.x初探(二)_第27张图片

这个构造函数中将listener都赋值给了 initialMulticaster,调用的是 SimpleApplicationEventMulticaster的父类的方法

springboot2.x初探(二)_第28张图片

将listener都赋值给了 detaultRetriever,然而在getApplicationListeners方法中有这样一个方法:

springboot2.x初探(二)_第29张图片

我们看看这个方法:

springboot2.x初探(二)_第30张图片

在这个方法中,将detaultRetriever中的applicationListeners返回来了,并赋值给了retriver。

到这里就知道了那个getApplicationListeners方法究竟是从哪里获取的listeners了。

好接着往下看multicastEvent方法:

springboot2.x初探(二)_第31张图片

调用了一个invokeListener方法:

springboot2.x初探(二)_第32张图片

里面调用了 doInvokeListener方法:

springboot2.x初探(二)_第33张图片

最终还是调用了ApplicationListener的onApplicationEvent方法:

springboot2.x初探(二)_第34张图片

都有哪些listeners呢?看个启动过程截图:

springboot2.x初探(二)_第35张图片

我们看一个RestartApplicationListener:

springboot2.x初探(二)_第36张图片

springboot2.x初探(二)_第37张图片

再看一个DelegatingApplicationListener

springboot2.x初探(二)_第38张图片

其他的不挨个看了。

到这里这个starting方法先告一段落。(这里的观察者模式用的很溜呀,下面再补补这方面的知识。)

下面看第八步初始化运行参数

这个ApplicationArguments:

springboot2.x初探(二)_第39张图片

提供SpringApplication运行需要的参数。

springboot2.x初探(二)_第40张图片

我们跟一下代码:

springboot2.x初探(二)_第41张图片

springboot2.x初探(二)_第42张图片

看看parse方法:

springboot2.x初探(二)_第43张图片

就是对参数的解析,然后封装到了CommandLineArgs中,

springboot2.x初探(二)_第44张图片

跟到最后发现是这个:

springboot2.x初探(二)_第45张图片

设置成了一个PropertySource。

这部分的内容实在是很多,所以分成了几篇文章来写,后续的分析将在下篇文章继续。

你可能感兴趣的:(学习之路)