Spring Boot容器的启动流程如下图所示:
一、执行注解:扫描、载入自动配置Bean
@SpringBootApplication注解的理解请参考(一)、Spring Boot之@SpringBootApplication注解的理解
二、SpringApplication.run()具体容器启动流程
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);//1.获取监听器
listeners.starting();-->启动!
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,//2.准备好环境,触发ApplicationEnvironmentPreparedEvent事件
applicationArguments);
Banner printedBanner = printBanner(environment);//打印启动提示字符,默认spring的字符图
context = createApplicationContext();//实例化一个可配置应用上下文
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,//3.准备上下文
printedBanner);
refreshContext(context);//4.刷新上下文
afterRefresh(context, applicationArguments);//5.刷新上下文后
listeners.finished(context, null);--关闭!
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
1、获取监听器:实际上就是SpringApplicationRunListeners类
1.1、载入工厂名称:loadFactoryNames
当前类加载器从META-INF/spring.factories文件中获取SpringApplicationRunListener类的配置
实际是获取了META-INF/spring.factories文件中# Run Listeners 模块的内容。
1.2、创建Spring工厂实例createSpingFactoriesInstances
根据载入工厂名称得到的Set<String> names生成“时间发布启动监听器”工厂实例。
2、准备好环境
3、准备上下文
4、 刷新上下文
5、 上下文刷新之后
Spring Boot 提供了两个供用户自己拓展的接口:ApplicationRunner和CommandLineRunner,可以在容器启动完毕后(上下文刷新后)执行,做一些类似数据初始化的操作。
这两个的区别在于参数不同,要用哪个根据自己实际情况而定。
@FunctionalInterface
public interface ApplicationRunner {
void run(ApplicationArguments var1) throws Exception;
}
@FunctionalInterface
public interface CommandLineRunner {
void run(String... var1) throws Exception;
}
CommandLineRunner中执行的参数是原始java启动类main方法的String[] args字符串数组参数,而ApplicationRunner的参数是经过处理提供一些方法。