SpringBoot启动过程
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}java
SpringApplication静态方法run
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
只做了两件事:
- new SpringApplication对象
- 执行该对象的run方法
SpringApplication对象初始化
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 资源加载器,初始为 null
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 确定应用程序类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 获取引导器
// META-INF/spring.factories 文件中找 org.springframework.boot.Bootstrapper
// 寻找的顺序:classpath → spring-beans → boot-devtools → springboot → boot-autoconfigure
this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
// 获取初始化器 META-INF/spring.factories 文件中找org.springframework.context.ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 初始化监听器 META-INF/spring.factories 文件中找org.springframework.context.ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 设置运行主类
this.mainApplicationClass = deduceMainApplicationClass();
}
对象初始化的几件事情:
- 确定程序的应用类型(NONE,SERVLET,WEBFLUX)
- 解析META-INF/spring.factories文件
- 获取引导器,获取初始化器,获取监听器
- 设置运行时的主类
getBootstrapRegistryInitializersFromSpringFactories()详解
@SuppressWarnings("deprecation")
private List<BootstrapRegistryInitializer> getBootstrapRegistryInitializersFromSpringFactories() {
ArrayList<BootstrapRegistryInitializer> initializers = new ArrayList<>();
getSpringFactoriesInstances(Bootstrapper.class).stream()
.map((bootstrapper) -> ((BootstrapRegistryInitializer) bootstrapper::initialize))
.forEach(initializers::add);
initializers.addAll(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
return initializers;
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 加载所有spring.factories文件,并放入缓存,提升后续读取效率
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 通过反射将其初始化
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
初始化初始化器ApplicationContextInitlializer/初始化监听器ApplicationListener
过程大致同上,只不过是从缓存获取spring.factories
run方法
public ConfigurableApplicationContext run(String... args) {
// 定义时间watch
StopWatch stopWatch = new StopWatch();
// 启动时间计时
stopWatch.start();
// 创建引导上下文环境
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 进入headless
configureHeadlessProperty();
// 获取应用程序运行监听监听器,META-INF/spring.factories 文件中找 org.springframework.boot.SpringApplicationRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 监听器启动,遍历所有的运行监听器调用 starting 方法
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境信息
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 配置忽略bean信息
configureIgnoreBeanInfo(environment);
// 打印banner
Banner printedBanner = printBanner(environment);
// 创建应用上下文容器,创建 IOC 容器
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 配置 IOC 容器的基本信息
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 刷新 IOC 容器
/* 1. Spring 的容器启动流程
* 2. invokeBeanFactoryPostProcessors(beanFactory):实现了自动装配
* 3. onRefresh():创建 WebServer 使用该接口
*/
refreshContext(context);
// 刷新后操作
afterRefresh(context, applicationArguments);
// 记录启动时间
stopWatch.stop();
// 是否要打印启动日志
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 事件广播:启动完成
listeners.started(context);
callRunners(context, applicationArguments);
}catch (Throwable ex) {
// 事件广播: 启动失败了
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
// 事件广播:容器开始运行
listeners.running(context);
}catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}
private DefaultBootstrapContext createBootstrapContext() {
//创建默认的引导类环境
DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
// 遍历所有的引导器,调用其initialize方法,完成初始化设置
this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
return bootstrapContext;
}
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
// 创建或返回基础环境信息对象 reative/servlet/default
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 读取所有配置源的属性值配置环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 属性值绑定环境信息
ConfigurationPropertySources.attach(environment);
// 运行监听器调用,environmentPrepared(),EventPublishingRunListener 发布事件通知所有的监听器当前环境准备完成
listeners.environmentPrepared(bootstrapContext, environment);
// 将defaultProperties属性移到配置源最后
DefaultPropertiesPropertySource.moveToEnd(environment);
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
"Environment prefix cannot be set via properties.");
// 与容器绑定当前环境
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
// 重新将属性值绑定环境信息
ConfigurationPropertySources.attach(environment);
return environment;
}
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
// 初始化beanName生成器
postProcessApplicationContext(context);
// 获取所有的初始化器调用 initialize() 方法进行初始化
applyInitializers(context);
// 所有的运行监听器调用 environmentPrepared() 方法,EventPublishingRunListener 发布事件通知 IOC 容器准备完成
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
// 所有的运行监听器调用 contextLoaded() 方法,通知 IOC 加载完成
listeners.contextLoaded(context);
}
run方法核心操作:
- 定义时间watch,记录当前时间
- 创建引导上下文环境
- 获取所有的运行监听监听器,并启动
- 获取参数持有类
- 准备环境信息
- 配置忽略的bean信息
- 打印banner
- 创建ioc容器
- 配置ioc容器基本信息
- 刷新ioc容器(容器初始化、自动装配)
- 刷新后操作(给用户提供扩展空间)
- 记录启动时间,广播启动事件
- 执行后置runner