SpringBoot启动流程分析原理(一)
2021-06-09 12:03
标签:rom str 创建 new 初始化过程 电脑 use ima argument 我们都知道 很多程序员都感慨 首先,我们先介绍下我们的演示的项目环境,我们先试用 接下来就只在 pom.xmL文件中添加一个web工程的依赖,是为了观察后面容器类型的源码。 这样我们的环境就准备好了。 到这里会执行 new SpringApplication(primarySources)创建spring应用对象,继续F7往下跟会执行 SpringApplication构造器 很多不为人知的事情都是发生在这个对象初始化的时候,这里我们都来一一解密 这段代码是来推断我们的应用是哪种web应用程序 当然一开始我们加入了web的依赖,所以我们是 servlet 容器。 在设置初始化应用context的时候,是先执行了 我们先来看看他是如何加载到这些类 这里有两个加载配置类的地方其实都指向了 双击Shifi搜索spring.factories可以看到它存在于以下工程中 从Map中根据 最关键的的还是这句 也就是这个最关键的代码了 到这里就完成了 这篇文章主要是给大家说了下 SpringBoot启动流程分析原理(一) 标签:rom str 创建 new 初始化过程 电脑 use ima argument 原文地址:https://www.cnblogs.com/reminis/p/14486867.html
SpringBoot
自问世以来,一直有一个响亮的口号"约定优于配置",其实一种按约定编程的软件设计范式,目的在于减少软件开发人员在工作中的各种繁琐的配置,我们都知道传统的SSM框架的组合,会伴随着大量的繁琐的配置;稍有不慎,就可能各种bug,被人发现还以为我们技术很菜。而SpringBoot
的出现不仅大大提高的开发人员的效率,还能避免由于"手抖"带来的配置错误。SpringBoot
的到来大大解放了生产力,但是也有聪明的程序猿会多思考一下下,SpringBoot
是怎么做到的约定的配置?它配置在了哪里?又是怎么启动的作用等等一系列的问号在跟女朋友花前月下的时候,依然会时不时冒出来。这严重影响了程序猿们的"幸"福生活,为了能广大"程序猿"同胞过上幸福美满的生活,今天咱么就来一起跟随源码探究下SpringBoot
到底是如何做到"约定优于配置"的。Spring Initializr
来创建一个SpirngBoot
工程。我们使用的版本是SpringBoot 2.4.3.RELEASE
我们跟着 SpringBoot
的源码来探究它的启动流程,首先,先找到这个应用程序的入口主方法,在上面打一个断点:
启动之后,F7进入到 run()方法,我的电脑是点击F7(Step into) //SpringApplication构造器
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
// 此处省略源码...
// 资源加载器
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
// 1.可能的web应用程序类型的类型。
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrappers = new ArrayList(this.getSpringFactoriesInstances(Bootstrapper.class));
// 2.设置初始化应用context
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 3.设置初始化监听
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
// 4.推演主程序类
this.mainApplicationClass = this.deduceMainApplicationClass();
}
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
return REACTIVE;
} else {
String[] var0 = SERVLET_INDICATOR_CLASSES;
int var1 = var0.length;
for(int var2 = 0; var2
1. 推断web 应用类型
public enum WebApplicationType{
NONE,// 不是web应用
SERVLET,// servlet容器
REACTIVE; // 反应型web应用(webflux)
}
2. 初始化应用上下文
getSpringFactoriesInstances(ApplicationContextInitializer.class)
方法,参数是ApplicationContextInitializer.class
字节码对象。 private
private static Map
META-INF/spring.factories
,通过断点我们可以看到应用程序是加载了以下几个jar下的 spring.factories
文件。
spring-boot-2.4.3.RELEASE.jar
下的 spring.factories (截图未完整截取)spring-boot-autoconfigure-2.4.3.RELEASE.jar
下的 spring.factoriesspring-beans-2.4.3.RELEASE.jar
下的 spring.factoriesorg.springframework.context.ApplicationContextInitializer
的类型拿到需要的类初始化类,断点进入 getOrDefault(factoryClassName,Collections.emptyList());方法
之后就是把加载到的需要初始化的类进行实例化添加到一个集合中等待备用3. 初始化监听器类
当我们跟进去之后,会发现在初始化监听类的时候和上面初始化应用上下文是一样的代码。唯一不同的是 getSpringFactoriesInstances(ApplicationListener.class))传进去的是·ApplicationListener.class 所以这里就不再赘述。4. 推演主程序类
this.mainApplicationClass = this.deduceMainApplicationClass();
SpringBoot
启动过程中初始化SpringApplication 的过程。SpringBoot
启动过程中初始化SpringApplication
的流程,大致可以分为四个步骤∶
通过这样四个步骤就完成了第一步 SpringApplication 的初始化过程。
上一篇:Java方法的重载
下一篇:# Java的可变参数
文章标题:SpringBoot启动流程分析原理(一)
文章链接:http://soscw.com/index.php/essay/92668.html