这篇文章接着 springboot2.x初探(一)
上篇文章中我们对 1 处的代码进行了分析,这篇文章来继续分析 2 处的代码:
由于这个方法比较长所以截了两个图,下面我们就按照截图中步骤的编号来一个一个看。
我们先来看看 1 处的StopWatch是什么
从类上的注释可以知道,这就是一个简单的记录开始时间和结束时间的功能的封装,它是非线程安全的。它的start 方法如下:
可以看到就是记录了一个任务名字为空的任务的开始时间。
4处的 SpringBootExceptionReporter:
它就是应用启动过程中发生错误的时候给用户抛出异常用的。
5 处的配置 java.awt.headless 属性的值,默认为 true
这个 java.awt.headless 是做什么用的呢?查到了一篇这样的博客:
https://blog.csdn.net/wodeyuer125/article/details/50502914
6 处的监听器:
它是SpringApplication 的run方法的监听器。
它的 starting方法会在run方法开始的时候马上调用。
通过 getRunListeners方法获取 SpringApplicationRunListener类的实现类的实例:
看一个listener实现类:
7处的starting
这里的 initialMulticaster :
先看看这个 SpringApplicationRunListener的实现类:
它使用一个内部的广播器来在context刷新之前发布触发的事件。
它就是将事件广播给所有注册的监听器,让监听器忽略不感兴趣的事件。
具体的广播方法在SimpleApplicationEventMulticaster类中,如下:
可以看到每个listener都使用了一个executor来调用,其中调用了一个 resolveDefaultEventType的方法,
这里有个判断判断传入的参数是不是 ResolvableTypeProvider的实例,我们上面实例化的是一个ApplicationStartingEvent:
我们看看这个ApplicationStartingEvent是不是实现了ResolvableTypeProvider接口:
这个过程中可以发现这个ApplicationStartingEvent就是对SpringApplication和参数的一个封装,同时很明显,它没有实现ResolvableTypeProvider接口,所以在 forInstance方法中调用的是:
接着看这个 forClass是怎么回事:
为传入的类返回了一个 ResolvableType,
可以看到这个 ResolvableType就是记录传入的类的类型,这个类型做什么用呢?
它在 getApplicationListeners方法中被调用了:
其中的ListenerCacheKey:
从
这里看到ListenerCacheKey竟然是一个Map的key,它是一个对象但是作为一个key了,那么它肯定重写了 hashcode和equals方法,我们看看:
果然如此,这里面具体的内容不在今天分析范围。接着往下看:
这个ListenerRetriever是一个私有的内部类,
看到这里的时候就有个疑问这个 ListenerRetriever中的applicationListeners是什么时候赋值的?
然后想到了之前的获取runlisteners方法中有获取实例化的runlisteners,看到了其中的types就是构造函数的参数类型,然后把它自己(SpringApplication)和args参数传了进去。
然后看到
这个构造函数中将listener都赋值给了 initialMulticaster,调用的是 SimpleApplicationEventMulticaster的父类的方法
将listener都赋值给了 detaultRetriever,然而在getApplicationListeners方法中有这样一个方法:
我们看看这个方法:
在这个方法中,将detaultRetriever中的applicationListeners返回来了,并赋值给了retriver。
到这里就知道了那个getApplicationListeners方法究竟是从哪里获取的listeners了。
好接着往下看multicastEvent方法:
调用了一个invokeListener方法:
里面调用了 doInvokeListener方法:
最终还是调用了ApplicationListener的onApplicationEvent方法:
都有哪些listeners呢?看个启动过程截图:
我们看一个RestartApplicationListener:
再看一个DelegatingApplicationListener
其他的不挨个看了。
到这里这个starting方法先告一段落。(这里的观察者模式用的很溜呀,下面再补补这方面的知识。)
下面看第八步初始化运行参数
这个ApplicationArguments:
提供SpringApplication运行需要的参数。
我们跟一下代码:
看看parse方法:
就是对参数的解析,然后封装到了CommandLineArgs中,
跟到最后发现是这个:
设置成了一个PropertySource。
这部分的内容实在是很多,所以分成了几篇文章来写,后续的分析将在下篇文章继续。