有道无术,术尚可求,有术无道,止于术。
本系列Spring Boot版本2.7.0
在上篇文档,我们介绍了创建SpringApplication
对象,然后调用run
方法启动,在run
方法中执行了很多步骤,接下来我们一步步分析。
我们知道在Spring 中有一个ApplicationContext
(IOC容器),既可以创建bean、获取bean、还支持国际化、事件广播、获取资源等BeanFactory
不具备的功能。
在Spring Boot 启动开始阶段,需要初始化一些东西,这个时候并不会直接创建ApplicationContext
,而是先创建BootstrapContext
,在ApplicationContext
完全创建好之前负责启动和准备环境(Environment)的一些操作。
实际上它也是一个IOC 容器,可以看到其接口也定义了获取Bean 的方法。
它的作用就是在启动阶段,创建一个引导性质的容器,先去负责一些初始化操作。
BootstrapRegistry
就提供了在启动开始阶段,ApplicationContext
完全创建好之前,负责Bean 实例注册的功能。
可以看到该接口的方法,都是用于注册。
DefaultBootstrapContext
实现了BootstrapRegistry
和BootstrapContext
接口,他们都是由Spring Boot 自己提供了接口。
可以看到,DefaultBootstrapContext
就是一个简单的IOC 容器,实现了注册 Bean 和获取Bean 的一些方法。
只所以设计一个引导的思想,就是因为在刚开始启动阶段,而这时候应用的IOC 容器并没有创建好,就用要这个引导上下文去完成一些初始化的操作。
BootstrapRegistryInitializer
从字面上看是引导程序注册初始化器的意思。
只声明了一个方法,传入了一个引导注册器参数。
该接口的功能就是对BootstrapRegistry
进行初始化操作。
@FunctionalInterface
public interface BootstrapRegistryInitializer {
void initialize(BootstrapRegistry registry);
}
run
方法的第一步就是执行了createBootstrapContext()
,从中文意思上看,是创建一个引导上下文。
// 开始时间
long startTime = System.nanoTime();
// 初始化启动上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
createBootstrapContext()
只有两步:
DefaultBootstrapContext
对象BootstrapRegistryInitializer
对象的初始化方法 private DefaultBootstrapContext createBootstrapContext() {
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
bootstrapRegistryInitializers
是在创建SpringApplication
对象的时候通过SPI 机制在spring.factories
文件中获取的BootstrapRegistryInitializer
实例对象。
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
bootstrapRegistryInitializers
集合中,这里没有找到实例,所有也没有进一步操作。
最终,经过简单的步骤,DefaultBootstrapContext
对象就常见成功了,实际查看,发现该类没有什么东西: