版权声明:版权所有,翻版我也没办法!!! https://blog.csdn.net/tebtebtebteb/article/details/82817478
今天来简单的说一下关于SpringBoot的启动流程,在整个启动配置中,有几个比较重要的事件回调机制需要特别注意,先列出:
- ApplicationContextInitializer
- SpringApplicationRunListener
- ApplicationRunner
- CommandLineRunner
下面的代码是SpringBoot的启动类
@SpringBootApplication
public class SpringBoot06DataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot06DataJpaApplication.class, args);
}
}
进入run()方法中查看:
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return (new SpringApplication(sources)).run(args);
}
从run()方法中可以看出,run()方法的启动分为两步:
- 创建SpringApplication对象
- 运行run()方法
下面分析这两步具体做了什么。
1.创建SpringApplication对象
public SpringApplication(Object... sources) {
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.initialize(sources);
}
执行SpringApplication的构造方法,创建对象,接着执行initialize()初始化方法
private void initialize(Object[] sources) {
//保存主配置类
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//判断当前应用是否为web应用
this.webEnvironment = this.deduceWebEnvironment();
//从类路径下找到META_INF/spring.factories配置的所有ApplicationContextInitializer,并保存
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//从类路径下找到META_INF/spring.factories配置的所有ApplicationListener,然后保存起来
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//从多个配置类中找到有main方法的主配置类
this.mainApplicationClass = this.deduceMainApplicationClass();
}
- //从类路径下找到META_INF/spring.factories配置的所有ApplicationContextInitializer,例如:
点击进入spring.factories
进入setInitializers()方法中,可以查看在当前项目中找到的ApplicationContextInitializer的个数
同理, //从类路径下找到META_INF/spring.factories配置的所有ApplicationListener,然后保存起来
至此,SpringApplication对象创建完毕。
2.执行run()方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
this.configureHeadlessProperty();
//从类路径下的META-INF/spring.factories中获取SpringApplicationRunListeners
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//回调所有的获取SpringApplicationRunListener.starting()方法
listeners.starting();
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境(进入prepareEnvironment()方法中可以看到创建环境完成后将回调
SpringApplicationRunListeners的environmentPrepared()方法,表示环境准备完成 )
ConfigurableEnvironment environment = this.prepareEnvironment(listeners,
applicationArguments);
//环境准备好之后就打印printBanner(即SpringBoot的在启动时的logo)
Banner printedBanner = this.printBanner(environment);
//创建一个ApplicationContext IOC容器,主要是决定创建web的ioc还是普通的ioc
context = this.createApplicationContext();
new FailureAnalyzers(context);
//准备上下文环境,将environment保存到ioc中,而且要执行applyInitializers()方法;
//applyInitializers():回调上面说到的所有的ApplicationContextInitializer的
// initialize()方法;此外,还要回调前面说到的所有的SpringApplicationRunListener的
// contextPrepared()方法
this.prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//刷新容器:ioc容器初始化(如果是web应用,还会创建嵌入式的Tomcat容器)
this.refreshContext(context);
//从IOC容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
//ApplicationRunner先回调,CommandLineRunner后回调,有优先级。
this.afterRefresh(context, applicationArguments);
//所有的SpringApplicationRunListener回调finished()方法
listeners.finished(context, (Throwable)null);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted
(this.getApplicationLog(), stopWatch);
}
//整个SpringBoot应用启动完成以后返回启动的IOC容器
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
throw new IllegalStateException(var9);
}
}