当前,大部分的企业级项目都在使用springCloud微服务解决方案,而springBoot是为spingCloud微服务解决方案的基石,博主从2019年开始接触使用springBoot进行项目开发,一路走来,感觉springBoot实在是好用,但是由于工作的原因,对于里面的原理一直都是一知半解,正好离职一段时间,刚好对其做一个整理。
springBoot之所以好用,个人觉得主要体现在如下几点:
1.springBoot可以帮助开发者快速整合第三方的框架;
2.springBoot完全去除了xml配置,完全采用注解形式;
3.springBoot内嵌可http服务器,我们不需要外置的tomcat服务器就可以将项目启动起来;
4.springBoot自带监控功能 Actuator,可以实现对程序内部运行情况进行监控,比如 Bean 加载情况、环境变量、日志信息、线程信息等。当然也可以自定义跟业务相关的监控,通过Actuator 的端点信息进行暴露。
那么我们先来了解一下springBoot的整体框架:
接下来我们从run方法开始研究一下springBoot的启动流程:
1.启动我们自己编写的程序入口main方法
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
2.首先会创建一个SpringApplication对象,并且在其构造方法里面会判断是否是web环境并且开始加载一些类到项目中,最后执行SpringApplication的run方法,正式开始启动springBoot。
public SpringApplication(Object... sources) {
initialize(sources);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
//判断当前classpath是否有加载我们的servlet类,即判断是否是web环境
this.webEnvironment = deduceWebEnvironment();
//加载所有classpath下面的META-INF/spring.factories ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//加载所有classpath下面的META-INF/spring.factories ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//推断main方法所在的类
this.mainApplicationClass = deduceMainApplicationClass();
}
//执行新建好SpringApplication类的run方法
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
3.执行run方法
public ConfigurableApplicationContext run(String... args) {
// 1.记录springBoot项目启动时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 2.声明应用上下文对象
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
// 3.设置系统属性 headless 的值 java.awt.headless
configureHeadlessProperty();
// 4.创建所有 Spring 运行监听器循环调用监听starting方法
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 5.处理 args 参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 6.准备环境,读取我们的配置文件到springBoot容器中
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
// 7.创建 Banner 的打印类,并且打印springBoot banner
Banner printedBanner = printBanner(environment);
// 8.创建应用上下文
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
// 9.准备应用上下文
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 10.刷新应用上下文
refreshContext(context);
// 11.应用上下文刷新之后的事件的处理
afterRefresh(context, applicationArguments);
// 12.发布应用上下文启动完成事件
listeners.finished(context, null);
// 13.停止计时监控类
stopWatch.stop();
// 14.输出日志记录执行主类名、时间信息
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 15.返回应用上下文对象
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
此时我们就拿到了spring的上下文对象了,籍此可以做一下定制化的操作。
好了,springBoot的启动流程到这里就分析结束了!有问题欢迎大家来一起留言探讨!!!