概述
Spring Boot框架带来一个Web应用启动的重大变化。 Java的Web应用部署都是通过容器,如:Tomcat、JBoss、Weblogic、Undertow等,一般都是将Java的Web应用构建成war、ear包再部署到相关的容器中。 Spring Boot带来了另外一种方式,就是可以将Web应用构建Jar包直接通过java命令启动,简化了应用的部署启动。这种启动方式底层技术并没有实际的变化,而是通过内嵌容器的方式取代外部容器,比如:spring-boot-starter-web默认使用Tomcat内嵌容器,你也可以选择使用其他内嵌容器。 在这篇文章里面主要是之前阅读了一些Spring Boot的启动源码,对Spring Boot启动流程作了一些简单的梳理。
Spring Boot应用启动方式
上文说到,Spring Boot的Web应用可以构建Jar包直接启动,即Spring Boot应用可以通过main方法直接启动,应用启动入口代码如下:
/**
* @author: cent
* @email: 292462859@qq.com
* @date: 2019/2/9.
* @description:
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
可以发现,Spring Boot应用启动入口代码非常简单,通过SpringApplication.run(Class<?> primarySource, String... args)
方法启动,那么这个方法里面作用做了什么处理呢,下文主要就是对这个方法的源码进行简单的梳理~
Spring Boot应用启动解析
启动入口方法
Spring Boot启动核心方法代码如下,增加了简单注释,下文会对每一步骤进行简单解释:
public ConfigurableApplicationContext run(String... args) {
//1.初始化计时器
StopWatch stopWatch = new StopWatch();
//2.计时器启动
stopWatch.start();
//Spring上下文对象
ConfigurableApplicationContext context = null;
//异常通知者列表
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
//3.设置系统配置java.awt.headless
this.configureHeadlessProperty();
//4.获取所有启动时监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//5.启动监听器
listeners.starting();
//定义异常通知者列表
Collection exceptionReporters;
try {
//6.初始化应用启动参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//7.准备环境变量
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
//8.设置spring.beaninfo.ignore配置
this.configureIgnoreBeanInfo(environment);
//9.打印Banner
Banner printedBanner = this.printBanner(environment);
//10.创建上下文对象
context = this.createApplicationContext();
//11.获取Spring异常报告者Bean列表
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//12.准备上下文对象
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//13.刷新上下文对象
this.refreshContext(context);
//14.刷新上下文对象后续工作
this.afterRefresh(context, applicationArguments);
//15.停止计时
stopWatch.stop();
//16.打印启动信息
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
// 17.执行启动时监听器started方法
listeners.started(context);
//18.执行ApplicationRunner和CommandLineRunner
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
//处理运行异常
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
//19.执行启动时监听器running方法
listeners.running(context);
return context;
} catch (Throwable var9) {
//处理运行异常
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
启动流程解释
进一步阅读启动源码,梳理Spring Boot应用启动流程如下图,下图对每个步骤进行简单分析并说明,详细的代码逻辑需要看一下源码。
尾巴
上面的内容是个人阅读源码分析的结果,可能存在错误之处,欢迎指正。上面的分析结果还比较表层,如果需要深入了解Spring Boot启动原理,建议深入研究一下里面的源码。