spring作为主流的 Java Web 开发的开源框架,是Java 世界最为成功的框架,持续不断深入认识spring框架是Java程序员不变的追求。
在之前的博客中,我们分析了@SpringBootApplication注解的作用,阐述了分布式架构下自动引入其他模块的类的方法
@SpringBootApplication注解的理解——如何排除自动装配 & 分布式情况下如何自动加载 & nacos是怎么被发现的
本篇博客介绍SpringBoot项目是怎么run跑起来的,从SpringApplication.run()方法入手,进行了启动流程的拆解,分析了监听的类SpringApplicationRunListeners,事件生命周期相关的类EventPublishingRunListener,配置相关的类ConfigurableEnvironment。
1.从SpringApplication.run()方法入手,进行了启动流程的拆解;
2.分析了监听的类SpringApplicationRunListeners,事件生命周期相关的类EventPublishingRunListener;
3.配置相关的类ConfigurableEnvironment。
项目主启动类代码
点击查看run方法实现
再跟踪到run方法中
可以看到此处在创建SpringApplication对象,然后调用run方法,先查看构造方法代码
在该方法中调用另外一个构造方法,如下
设置监听器,此处设置11个监听器
然后再跟踪到run方法
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
// 创建所有 Spring 运行监听器并发布应用启动事件
SpringApplicationRunListeners listeners = this.getRunListeners(args);
// 启动各个SpringApplicationRunListener 监听器实例(EventPublishingRunListener)
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 初始化默认应用参数类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 根据运行监听器和应用参数来准备 Spring 环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
this.configureIgnoreBeanInfo(environment);
// 创建 Banner 打印类
Banner printedBanner = this.printBanner(environment);
// 创建应用上下文
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备应用上下文
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
// 刷新应用上下文
this.refreshContext(context);
// 应用上下文刷新后置处理 空操作
this.afterRefresh(context, applicationArguments);
// 止计时监控,和开始的纳秒数相减
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
// 输出日志记录执行主类名、时间信息
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
}
// 发布应用上下文启动完成事件
listeners.started(context, timeTakenToStartup);
// 执行所有 Runner 运行器
this.callRunners(context, applicationArguments);
} catch (Throwable var12) {
this.handleRunFailure(context, var12, listeners);
throw new IllegalStateException(var12);
}
try {
// 发布应用上下文就绪事件
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
// 返回应用上下文
return context;
} catch (Throwable var11) {
this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var11);
}
}
SpringApplicationRunListeners
SpringApplicationRunListeners中封装了多个SpringApplicationRunListener,这些监听器用来在整个启动流程中接收不同执行点事件通知的监听者,SpringApplicationRunListener接口规定了SpringBoot的生命周期,在各个生命周期广播相应的事件,调用实际的ApplicationListener类。
public interface SpringApplicationRunListener {
// run方法开始执行时
default void starting() {
}
// Environment准备好之后
default void environmentPrepared(ConfigurableEnvironment environment) {
}
// ApplicationContext准备好之后
default void contextPrepared(ConfigurableApplicationContext context) {
}
// ApplicationContext加载完成
default void contextLoaded(ConfigurableApplicationContext context) {
}
// run方法启动完成,回调ApplicationRunner和CommandLineRunner之前
default void started(ConfigurableApplicationContext context) {
}
// run方法执行完成,马上出方法栈时
default void running(ConfigurableApplicationContext context) {
}
// 运行异常时,执行的逻辑
default void failed(ConfigurableApplicationContext context, Throwable exception) {
}
}
Spring Boot定义的SpringApplicationRunListener实现类只有EventPublishingRunListener,主要是定义了其生命周期,并且在Spring Boot启动过程中完成回调。
进入查看
在构造函数中赋值了ApplicationContext和args,并且创建了SimpleApplicationEventMulticaster事件发送器。在SpringApplicationContext的refresh时会创建SimpleApplicationEventMulticaster,现在只是先创建出来,待执行refresh时会用到。
SpringApplicationRunListener生命周期和对应事件发送类型为:
生命周期 | 对应事件 |
---|---|
starting | ApplicationStartingEvent |
environmentPrepared | ApplicationEnvironmentPreparedEvent |
contextPrepared | ApplicationContextInitializedEvent |
contextLoaded | ApplicationPreparedEvent |
started | ApplicationStartedEvent |
running | ApplicationReadyEvent |
failed | ApplicationFailedEvent |
ApplicationArguments
获取程序启动参数,例如VM参数
ConfigurableEnvironment
ConfigurableEnvironment不仅提供了配置文件解析的数据,以及配置文件名称,还提供了PropertySource数据。其实配置文件的解析出来的数据,也是封装成了PropertySource放在ConfigurableEnvironment中
ConfigurableEnvironment是spring中非常重要的角色,可以通过它获得activeProfiles,来判断我们所使用的环境是dev还是test或者prod等等。还可以根据getProperty拿到配置中的信息并且提供类型转换功能,以及获取系统环境变量等信息。
1.从SpringApplication.run()方法入手,进行了启动流程的拆解;
2.分析了监听的类SpringApplicationRunListeners,事件生命周期相关的类EventPublishingRunListener;
3.配置相关的类ConfigurableEnvironment。