SpringApplication.run一共做了两件事,一件是创建SpringApplication对象,在该对象初始化时,找到配置的事件监听器,并保存起来.第二件事就是运行run方法,此时会将刚才保存的事件监听器根据当前时机触发不同的事件,比如容器初始化,容器创建完成等.同时也会刷新IoC容器,进行组件的扫描、创建、加载等工作.这两件事我都看过源码,我分别给你画个图细致讲一讲.
SpringApplication.run
SpringApplication.run
一共做了两件事,分别是
- 创建
SpringApplication
对象 - 利用创建好的
SpringApplication
对象,调用run
方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
public SpringApplication(Object... sources) {
initialize(sources);
}
创建SpringApplication
对象
- 保存主配类
- 判断当前是否为web应用
- 从类路径下找到/META-INF/spring.factories配置的所有ApplicationContextInitializer。并保存。
- 从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener。并保存。
- 从配置类中找到main方法的主配置类
private void initialize(Object[] sources) {
//1.保存主配类
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//2. 判断当前是否为web应用
this.webEnvironment = deduceWebEnvironment();
//从类路径下找到/META-INF/spring.factories配置的所有ApplicationContextInitializer。并保存。
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener。并保存。
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
调用run方法
- 从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener.
- 遍历所有ApplicationListener然后回调其starting事件。
- 封装命令行参数
- 准备环境,并遍历回调SpringApplicationRunListeners的environmentPrepared事件
- Banner打印.
- 根据是否是web环境来决定创建web容器还是普通的IOC容器
- 准备上下文环境,将environment保存到IOC容器当中
- 7-1. 执行applyInitializers方法:遍历回调ApplicationContextInitializer的initialize事件。
- 7-2. 遍历回调SpringApplicationRunListeners的contextPrepared事件
- 7-3. 继续回调SpringApplicationRunListeners的contextLoaded事件
- 刷新容器,此时进行组件的扫描,加载,创建等。
- 从IOC容器中获取所有实现ApplicationRunner和CommandLineRunner的实现类进行回调事件(先回调:ApplicationRunner,然后回调CommandLineRunner)
- 遍历回调SpringApplicationRunListeners的finished事件。
- 启动完成,返回IOC容器
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
//1. 从类路径下找到/META-INF/spring.factories配置的所有ApplicationListener
SpringApplicationRunListeners listeners = getRunListeners(args);
//2. 遍历所有ApplicationListener然后回调其starting事件
listeners.starting();
try {
//3. 封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//4. 准备环境,并遍历回调SpringApplicationRunListeners的environmentPrepared事件
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//5. Banner打印
Banner printedBanner = printBanner(environment);
//6. 根据是否是web环境来决定创建web容器还是普通的IOC容器
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
//7. 准备上下文环境,将environment保存到IOC容器当中
//7-1. 执行applyInitializers方法:遍历回调ApplicationContextInitializer的initialize事件
//7-2. 遍历回调SpringApplicationRunListeners的contextPrepared事件
//7-3. 继续回调SpringApplicationRunListeners的contextLoaded事件
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//8. 刷新容器,此时进行组件的扫描,加载,创建等。
refreshContext(context);
//9. 从IOC容器中获取所有实现ApplicationRunner和CommandLineRunner的实现类进行回调事件(先回调:ApplicationRunner,然后回调CommandLineRunner)
afterRefresh(context, applicationArguments);
//10. 遍历回调SpringApplicationRunListeners的finished事件
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//11. 启动完成,返回IOC容器
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}