一、springboot应用启动源码分析
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return (new SpringApplication(sources)).run(args);
}
【1】创建SpringApplication
对象
调用initialize(sources);
创建对象。流程:
private void initialize(Object[] sources) {
//1.保存主配置类
if(sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//2.判断当前应用是否是一个web应用
this.webEnvironment = deduceWebEnvironment();
//3.从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer,然后保存起来
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//4.从类路径下找到META-INF/spring.factories配置的所有ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//5.从多个配置类中找到含有"main"的主配置类
this.mainApplicationClass = deduceMainApplicationClass();
}
有6个initializer:
可以找到的ApplicationListener:
【2】运行run
方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
//从类路径下META‐INF/spring.factories获取SpringApplicationRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
//回调获取到的所有SpringApplicationRunListener对象的starting()方法
listeners.starting();
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//准备环境。创建环境完成后回调SpringApplicationRunListener.environmentPrepared()
//方法,表示环境已经准备完成
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
//打印springboot的图标
Banner printedBanner = printBanner(environment);
//创建ApplicationContext容器:决定创建的是web的ioc容器还是普通的ioc容器
context = createApplicationContext();
//出现异常以后做异常分析报告的
analyzers = new FailureAnalyzers(context);
//准备上下文环境:将environment保存到ioc容器中;而且执行applyInitializers()方法;
//applyInitializers():回调之前保存的所有的ApplicationContextInitializer的initialize方法;回调所有的
//SpringApplicationRunListener的contextPrepared();
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
///prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded();
//刷新容器:即ioc容器初始化的过程(如果是web应用,还会创建嵌入式的servlet容器)。
//扫描、加载、创建所有组件的地方
refreshContext(context);
//从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
//ApplicationRunner先回调,CommandLineRunner再回调
afterRefresh(context, applicationArguments);
//所有的SpringApplicationRunListener回调finished方法
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//整个SpringBoot应用启动完成以后返回启动的ioc容器
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
二、springboot应用启动原理总结
SpringApplication.run(主程序类):
– new SpringApplication(主程序类)
• 判断是否web应用
• 加载并保存所有ApplicationContextInitializer(META-INF/spring.factories)
• 加载并保存所有ApplicationListener
• 获取到主程序类
– run()
• 回调所有的SpringApplicationRunListener(META-INF/spring.factories)的starting
• 获取ApplicationArguments
• 准备环境&回调所有监听器( SpringApplicationRunListener )
的environmentPrepared
• 打印banner
信息
• 创建ioc容器对象
–AnnotationConfigEmbeddedWebApplicationContext(web环境容器)
– AnnotationConfigApplicationContext(普通环境容器)
• 准备环境
– 执行ApplicationContextInitializer. initialize()
– 监听器SpringApplicationRunListener
回调contextPrepared
– 加载主配置类定义信息
– 监听器SpringApplicationRunListener
回调contextLoaded
• 刷新启动IOC容器;
– 扫描加载所有容器中的组件
– 包括从META-INF/spring.factories
中获取的所有EnableAutoConfiguration
组件
• 回调容器中所有的ApplicationRunner
、CommandLineRunner
的run方法
• 监听器SpringApplicationRunListener
回调finished