有道无术,术尚可求,有术无道,止于术。
本系列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 对象就常见成功了,实际查看,发现该类没有什么东西:
