- 1、SpringApplication实例的初始化创建
- 1、 进入 SpringApplication方法
- 2、首先是进入带参数的构造方法
- 3、构建和初始化SpringApplication
- 4、第一项,进入deduceFromClasspath看如何获取环境
- 4.1、第一项的具体获取环境源码
- 5、第二项,进入getSpringFactoriesInstances方法
- 5.1、继续调用重载方法
- 5.2、进入getSpringFactoriesInstances方法
- 5.3、通过debug模式,进入loadFactoryNames方法
- 5.3.1、进入loadFactoryNames方法并运行
- 5.3.2、继续进入loadSpringFactories方法
- 5.3.2.1、看其如何加载配置文件
- 5.3.2.2、获取指定路径,然后通过loadProperties加载
- 5.3.2.3、最后返回的加载结果
- 5.3.3、根据传回的参数去创建对应的工厂
- 5.3.3.1、创建工厂的源码
- 5.3.4、对返回的实例进行排序
- 6、第三项,进入getSpringFactoriesInstances方法
- 6.1、最后返回的执行结果
- 7、第四项,进入deduceMainApplicationClass方法
- 7.1、右键选中Evaluate来试看一下返回结构
- 7.1.1、具体获取main方法的全限定类名
1、SpringApplication实例的初始化创建
查看SpringApplication实例对象初始化创建的源码信息,核心代码具体如下
1、 进入 SpringApplication方法
2、首先是进入带参数的构造方法
SpringApplication 实例化过程,首先是进入带参数的构造方法,最终回来到两个参数 的构造方法。
3、构建和初始化SpringApplication
开始需要对此4项 进行 重点分析。
4、第一项,进入deduceFromClasspath看如何获取环境
4.1、第一项的具体获取环境源码
返回类型是WebApplicationType的枚举类型, WebApplicationType 有三个枚举,三个枚举的解释如 其中注释 具体的判断逻辑如下:
WebApplicationType.REACTIVE classpath下存在 org.springframework.web.reactive.DispatcherHandler WebApplicationType.SERVLET classpath下存在javax.servlet.Servlet或者 org.springframework.web.context.ConfigurableWebApplicationContext
WebApplicationType.NONE 不满足以上条件。
第一项的说明如下: this.webApplicationType=WebApplicationType.deduceFromClasspath()用于判断当前webApplicationType应用的类型。deduceFromClasspath()方法用于查看Classpath类路径下是否存在某个特征类,从而判断当前webApplicationType类型是SERVLET应用(Spring5之前的传统MVC应用)还是REACTIVE应用(Spring5开始出现的WebFlux交互式应用)。
5、第二项,进入getSpringFactoriesInstances方法
5.1、继续调用重载方法
5.2、进入getSpringFactoriesInstances方法
5.3、通过debug模式,进入loadFactoryNames方法
5.3.1、进入loadFactoryNames方法并运行
然后 运行 一行,看其获取的 factoryTypeName
loadFactoryNames() 这个方法很重要,这个方法是spring-core中提供的从META-INF/spring.factories中获取指定的类 (key)的同一入口方法。 在这里,获取的是key为 org.springframework.context.ApplicationContextInitializer 的类。
5.3.2、继续进入loadSpringFactories方法
5.3.2.1、看其如何加载配置文件
5.3.2.2、获取指定路径,然后通过loadProperties加载
5.3.2.3、最后返回的加载结果
ApplicationContextInitializer 是Spring框架的类, 这个类的主要目的就是在 ConfigurableApplicationContext 调用refresh()方法之前,回调这个类的initialize方法。 通过 ConfigurableApplicationContext 的实例获取容器的环境Environment,从而实现对配置文件的 修改完善等工作
第二项的说明如下: this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class))
用于SpringApplication应用的初始化器设置。在初始化器设置过程中,
会使用Spring类加载器SpringFactoriesLoader从 META-INF/spring.factories 类路径下的META-INF下的spring.factores文件中获取所有可用的应用初始化器类ApplicationContextInitializer。
5.3.3、根据传回的参数去创建对应的工厂
5.3.3.1、创建工厂的源码
5.3.4、对返回的实例进行排序
其实也就是5.2中看到的第三个方法 sort
6、第三项,进入getSpringFactoriesInstances方法
这次和上面第二项走的流程是一样的。只不过此次获取的是简体器
(整个流程按第5点的全部走即可)
6.1、最后返回的执行结果
第三项的说明如下:
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class))用于SpringApplication应用的监听器设置。监听器设置的过程与上一步初始化器设置的过程基本一样,
也是使用SpringFactoriesLoader从META-INF/spring.factories类路径下的META-INF下的spring.factores文件中获取所有可用的监听器类ApplicationListener。
7、第四项,进入deduceMainApplicationClass方法
7.1、右键选中Evaluate来试看一下返回结构
(以前可能是先把流程走了,看返回结果,现在直接右键来查看,工具用起来很顺手啊)
7.1.1、具体获取main方法的全限定类名
第四项的说明如下:
this.mainApplicationClass=this.deduceMainApplicationClass()
用于推断并设置项目main()方法启动的主程序启动类
从上述源码可以看出,SpringApplication的初始化过程主要包括4部分
关于 SpringApplication 类的构造过程,到这里就梳理完了。纵观 SpringApplication 类的实例化过程,可以看到,合理的利用该类,就能在spring容器创建之前做一些预备工作,和定制化的需 求。
比如自定义SpringBoot的Banner,
比如自定义事件监听器,
再比如在容器refresh之前通过自定义 ApplicationContextInitializer 修改配置
一些配置或者获取指定的bean都是可以的