一步一步分析SpringBoot启动源码(二)

分享 未结 精帖 2 4252
KSE-music
KSE-music LV4 2018-07-16
悬赏:20积分
一、私有方法configureHeadlessProperty()
字面意思就是配置headless属性,那么headless是what?
Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标。

Headless模式虽然不是我们愿意见到的,但事实上我们却常常需要在该模式下工作,尤其是服务器端程序开发者。因为服务器(如提供Web服务的主机)往往可能缺少前述设备,但又需要使用他们提供的功能,生成相应的数据,以提供给客户端(如浏览器所在的配有相关的显示设备、键盘和鼠标的主机)。
二、SpringApplicationRunListeners listeners = getRunListeners(args);见方法名就知道它是干什么的,即获取Spring应用的监听器,一个完整的Spring应用运行监听器如下图:

这里要注意:
因为我这里分析的版本是1.5.13.RELEASE,而在2.0之后版本将整个过程做了调整且这块不向下兼容。
1、SpringApplicationRunListener的获取很前面的初始化器和监听器一样,通过解析META-INF/spring.factories中key为org.springframework.boot.SpringApplicationRunListener的值,这里我们发现只有一个,如下:



然后通过反射实例化(先获取public的构造器),而这里只有一个构造器如下:



接收两个参数,第一个是我们正在启动的Spring应用,第二个是args(通过main方法传入的),在这个方法体首先分别把这两个参数赋给成员变量,另外在这里new了一个应用事件发射器,同时添加前面解析得到所有监听器(已排序),目的是要给它当“观众”(事件接收者)。EventPublishingRunListener实例化,并其添加到SpringApplicationRunListeners(它是一个SpringApplicationRunListener的集合,即可以收集所有SpringApplicationRunListener),然后循环发布事件。可以看出这里是使用了观察者设计模式,在之后阅读源码过程,会发现很多地方都使用了设计模式,如:策略模式等。

2.listeners.starting();标识着应用正式启动。发布正在启动事件。SpringApplicationRunListeners要做的就是循环所有SpringApplicationRunListener(我们这里只有一个)并调用starting方法发布事件


这里实质调用的是EventPublishingRunListener里面的starting,而在这里它就使用了之前在构造它对象的时候一并初始化 的应用发射器SimpleApplicationEventMulticaster,这里发送的事件名称为ApplicationStartedEvent(名字取的不好,所以已经标识deprecation,2.0版本已纠正)。而事件的接收者就是前面所提到”观众”,但是,在这里它可不是给所有的发,而是过滤了一下,毕竟“己所不欲勿施于人”嘛,这里过滤的原则就是由事件类型和事件源共同决定,举个例子:就好比男人喜欢女人一样,但不是只要你是女人男的就喜欢,有的人说我喜欢四川的,而有的喜欢湖南的。
在这里过滤前后对比如下:



这里提醒 Mcn打头东西是我基于SpringBoot开发的一个自动化配置jar,没用到的,直接无视。
在发送事件的时候,首先判断了是否需要异步发送即有没Executor,如果是异步的还有个异步错误处理器ErrorHandler,由于默认启动这里都没有即同步启动,直接跳到doInvokeListener方法,这里调用了监听器的onApplicationEvent方法,此时不难发现这个方法就是我们创建监听器时所覆写的方法。从第二个监听器开始看即LoggingApplicationListener,在其onApplicationEvent方法通过if else if判断当前来的是什么时间类型(就好比来了个女的,你的看看她是不是来自四川一样),这里是启动事件类型,这里又调用了onApplicationStartingEvent方法,里面获取了Spring应用所使用的日志系统,而具体使用的是哪种日志实现由用户定。



BackgroundPreinitializer不处理该事件。
读者可以想想为什么该监听器不处理该事件,之前怎么没把它过滤掉?
DelegatingApplicationListener它也不处理该事件。不过读者可以想想这个东西是干嘛的?

LiquibaseServiceLocatorApplicationListener:class都没有,不讲了。
所有事件的发布以及接收的处理,模式都是一样的,后面发布的事件我就不一个个进去分析了,但是重要的还是要进去的,比如在上篇提到的ConfigFileApplicationListener
回帖