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