SpringBoot的启动很简单,通用的代码如下:
1 |
|
SpringApplication.run
方法实际执行的方法如下:
1 | public static ConfigurableApplicationContext run(Object[] sources, String[] args) { |
初始化SpringApplication
SpringApplication的构造函数中调用了initialize
方法来初始化SpringApplication:
1 | private void initialize(Object[] sources) { |
调用
deduceWebEnvironment
来判断当前的应用是否是web应用,并设置到webEnvironment
属性中。deduceWebEnvironment
方法通过获取1
2javax.servlet.Servlet
org.springframework.web.context.ConfigurableWebApplicationContext
这两个类来判断,如果能获得这两个类则说明是web应用,否则不是。
调用
getSpringFactoriesInstances
从spring.factories文件中找出key为ApplicationContextInitializer的类并实例化,然后调用setInitializers
方法设置到SpringApplication
的initializers
属性中。这个过程就是找出所有的应用程序初始化器。细节详见:获取初始化器当前的初始化器有如下几个:
1
2
3
4
5
6DelegatingApplicationContextInitializer
ContextIdApplicationContextInitializer
ConfigurationWarningsApplicationContextInitializer
ServerPortInfoApplicationContextInitializer
SharedMetadataReaderFactoryContextInitializer
AutoConfigurationReportLoggingInitializer调用
getSpringFactoriesInstances
从spring.factories文件中找出key为ApplicationListener的类并实例化,然后调用setListeners
方法设置到SpringApplication
的listeners
属性中。这个过程就是找出所有的应用程序事件监听器。细节详见:获取监听器当前的事件监听器有如下几个:
1
2
3
4
5
6
7
8
9
10ConfigFileApplicationListener
AnsiOutputApplicationListener
LoggingApplicationListener
ClasspathLoggingApplicationListener
BackgroundPreinitializer
DelegatingApplicationListener
ParentContextCloserApplicationListener
ClearCachesApplicationListener
FileEncodingApplicationListener
LiquibaseServiceLocatorApplicationListener调用
deduceMainApplicationClass
方法找出main类,就是这里的SpringBootDemoApplication
类
运行SpringApplication
SpringApplicationRunListeners和SpringApplicationRunListener类
SpringApplicationRunListeners内部持有SpringApplicationRunListener集合和1个Log日志类。用于SpringApplicationRunListener监听器的批量执行。
SpringApplicationRunListener用于监听SpringApplication的run方法的执行,它定义了5个步骤:
- starting:run方法执行的时候立马执行,对应的事件类型是ApplicationStartedEvent
- environmentPrepared:ApplicationContext创建之前并且环境信息准备好的时候调用,对应的事件类型是ApplicationEnvironmentPreparedEvent
- contextPrepared:ApplicationContext创建好并且在source加载之前调用一次,没有具体的对应事件
- contextLoaded:ApplicationContext创建并加载之后并在refresh之前调用,对应的事件类型是ApplicationPreparedEvent
- finished:run方法结束之前调用,对应事件的类型是ApplicationReadyEvent或ApplicationFailedEvent
SpringApplicationRunListener目前只有一个实现类EventPublishingRunListener,详见获取SpringApplicationRunListeners。它把监听的过程封装成了SpringApplicationEvent事件并让内部属性ApplicationEventMulticaster接口的实现类SimpleApplicationEventMulticaster广播出去,广播出去的事件对象会被SpringApplication中的listeners属性进行处理。
所以说SpringApplicationRunListener和ApplicationListener之间的关系是通过ApplicationEventMulticaster广播出去的SpringApplicationEvent所联系起来的。
run方法
初始化SpringApplication完成之后,调用run
方法运行:
1 | public ConfigurableApplicationContext run(String... args) { |
run方法执行完成之后,Spring容器也已经初始化完成,各种监听器和初始化器也做了相应的工作。具体步骤的分析见下文。
配置并准备环境:
1 | private ConfigurableEnvironment prepareEnvironment( |
创建Spring容器上下文:
1 | protected ConfigurableApplicationContext createApplicationContext() { |
配置Spring容器上下文:
1 | private void prepareContext(ConfigurableApplicationContext context, |
Spring容器创建之后回调方法postProcessApplicationContext:
1 | protected void postProcessApplicationContext(ConfigurableApplicationContext context) { |
初始化器开始工作:
1 | protected void applyInitializers(ConfigurableApplicationContext context) { |
首先调用getInitializers
方法获取之前取得的初始化器。之后调用初始化器的initialize
方法。
Spring容器创建完成之后会调用afterRefresh方法:
1 | protected void afterRefresh(ConfigurableApplicationContext context, |
一些细节
获取初始化器
初始化器的获取由SpringApplication.getSpringFactoriesInstances
方法完成:
1 | private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, |
SpringFactoriesLoader.loadFactoryNames
方法获取ApplicationContextInitializer
接口实现的类:
1 | public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { |
获取监听器
获取监听器的方法与获取初始化器的方法一致,唯一的区别在于获取org.springframework.context.ApplicationListener
接口的实现类
获取SpringApplicationRunListeners
首先看getRunListeners
方法:
1 | private SpringApplicationRunListeners getRunListeners(String[] args) { |
可以看到通过调用构造函数来实例化SpringApplicationRunListeners
,传入的参数有logger以及调用getSpringFactoriesInstance
获得的SpringApplicationRunListener
集合。
再看getSpringFactoriesInstance
方法,它和获取初始化器的方法一样,获取的接口类型是org.springframework.boot.SpringApplicationRunListener
。获取到的实现类为org.springframework.boot.context.event.EventPublishRunListener
。
SpringApplicationRunListeners的工作原理
以启动过程中的listeners.starting()
方法为例:
1 | public void starting() { |
this.listeners
中只有一个元素:EventPublishingRunListener
。它的starting
方法如下:
1 | public void starting() { |
其中this.initialMulticaster
是SimpleApplicationEventMulticaster
的实例。multicastEvent
方法如下:
1 | public void multicastEvent(ApplicationEvent event) { |
首先调用getApplicationListeners
方法,根据event的type获得ApplicationListener
列表,其中type为ApplicationStartedEvent
。getApplicationListeners
方法中调用retrieveApplicationListeners
获取支持eventType的listener:
1 | private Collection<ApplicationListener<?>> retrieveApplicationListeners( |
ApplicationStartedEvent
事件返回的是4个listener:
- LoggingApplicationListener
- BackgroundPreinitializer
- DelegatingApplicationListener
- LiquibaseServiceLocatorApplicationListener
回到multicastEvent
方法,调用getTaskExecutor
获取executor。executor为空,调用invokeListener
:
1 | protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) { |
获取errorHandler,errorHandler为空,调用doInvokeListener
方法:
1 | private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { |
可以看到,doInvokeListener
方法直接调用了listener的onApplicationEvent
方法。