springboot启动过程(基于版本2.0.5.release)
直接上代码
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
进到run
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
String[] args) {
//第一步 new SpringApplication
//第二步 执行run
return new SpringApplication(primarySources).run(args);
}
第一步new SpringApplication
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断是否是web程序并且赋值
this.webApplicationType = deduceWebApplicationType();
// 从spring.factories文件中找出key为ApplicationContextInitializer的类并实例化后设置到SpringApplication
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
// 从spring.factories文件中找出key为ApplicationListener的类并实例化后设置到SpringApplication
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//找到main方法
this.mainApplicationClass = deduceMainApplicationClass();
}
第二步 run
public ConfigurableApplicationContext run(String... args) {
//任务执行观察器
StopWatch stopWatch = new StopWatch();
//开始执行,记录时间
stopWatch.start();
//定义一个容器
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//获取所有的监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
//执行相应的事件
listeners.starting();
try {
//构造应用参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//创建应用环境信息
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//配置环境信息
configureIgnoreBeanInfo(environment);
//打印启动banner
Banner printedBanner = printBanner(environment);
//创建spring容器
context = createApplicationContext();
//获取并打印Spring启动过程中的异常信息
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//刷新容器前准备 环境 回调方法 初始化器 广播 注册一些东西
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//刷新容器
refreshContext(context);
//初始化容器后的一些操作
afterRefresh(context, applicationArguments);
//执行结束。记录时间
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//发布事件
listeners.started(context);
//找出Spring容器中Runner接口的实现类,然后执行(ApplicationRunner,CommandLineRunner)
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
prepareContext
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置环境信息
context.setEnvironment(environment);
//回调
postProcessApplicationContext(context);
//初始化器开始工作
applyInitializers(context);
//监听器广播
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
//给容器注册应用参数
// Add boot specific singleton beans
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
总结
SpringBoot启动的时候,分为两步
1.构造SpringApplication
2.执行run方法
构造SpringApplication
- 把参数sources设置到SpringApplication属性中
- 判断是否是web程序并且赋值
- 找出所有的初始化器并设置到SpringApplication中
- 找出所有的应用程序监听器并设置到SpringApplication中
- 找出main类
执行run方法
- 构造一个StopWatch,观察SpringApplication的执行
- 找出所有的SpringApplicationRunListener并封装到SpringApplicationRunListeners中,用于监听run方法的执行。监听的过程中会封装成事件并广播出去让初始化过程中产生的应用程序监听器进行监听
- 构造Spring容器(ApplicationContext),并返回
3.1 根据环境创建Spring容器
3.2 执行初始化过程中产生的初始化器
3.3 Spring容器的刷新(创建对象实例)
3.4从Spring容器中找出ApplicationRunner和CommandLineRunner接口的实现类并排序后依次执行
下一篇刷新容器:https://blog.csdn.net/gcxxr/article/details/106720355