继上一篇博客分析了Spring Boot自动装配过程及原理。今天聊一聊spring boot启动到底做了哪些事情,如果不了解spring内部机制的,可能有些过程看不明白。
我个人理解springboot启动分为三个大步骤:
一、创建SpringApplication对象
SpringApplication的构造方法会初始化7个比较重要的参数:primarySources就是我们传入的被@SpringBootApplication注解的主类,接下来推测该应用是什么类型,配置有三种类型,但是一般我们启动的都是Servlet应用,不必过多纠缠。
接下来会读取所有spring.factories文件中BootstrapRegistryInitializer.class,ApplicationContextInitializer.class类型和ApplicationListener.class类型分别赋值给对应的属性, 最后推测书main()方法所在的类
二、调用SpringApplication的run方法
创建SpringApplication对象并初始化后,开始执行run()方法:主要是创建、初始化启动spring容器,解析配置类,随后去自动装配,并发布相应的事件等
1、首先创建DefaultBootstrapContext对象,我也不知道他有啥用,在spring启动完成后他会被关闭掉,就不研究它了。
2、从spring.factories中获取监听器,默认只有一个EventPublishingRunListener,它spring启动的过程中会发布各种不同的事件
3、紧接着就发布了一个事件(ApplicationStartingEvent),会有三个监听器被触发执行如下图
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
this.initialMulticaster
.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
这些监听器做了啥,我没研究。
4、将run()方法的参数封装为DefaultApplicationArguments对象
5、准备环境(prepareEnvironment),解析操作系统参数,jvm参数,程序员配置的yaml、yml、properties等参数。
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(bootstrapContext, environment);
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = convertEnvironment(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
首先根据应用类型创建ApplicationServletEnvironment对象, 然后向environment对象中添加四个PropertySource对象,这个步骤很恶心,我没有深究。有空再回来研究
6、创建spring容器
7、将environment设置到spring容器,然后初始化spring容器,发布ApplicationContextInitializedEvent事件表示spring容器初始化结束,随后会注册一些单例bean到spring容器,最后发布ApplicationPreparedEvent事件,表示Spring容器已经准备好
8、最关键一步来了,调用refresh()刷新spring容器,解析配置,spring会帮我们解析@EnableAutoConfiguration注解并自动装配(见步骤三),启动web容器等操作
8、最后就分别发布两个事件 :ApplicationStartedEvent事件表示spring启动完成和ApplicationReadyEvent事件表示spring容器已经准备好,返回spring容器
结束。
三、在执行run方法的过程中创建的spring容器会解析@SpringBootApplication注解进行自动装配
加载spring.factories文件中自动装配类,根据条件判断加载需要的自动装配类,值得关注的自动装配就是默认会启动tomcat而不是jetty或者undertow,因为springboot内部只配置了内嵌的tomcat依赖。前面的博客已经分析过这个步骤。