springboot源码深度解析 springboot源码怎么看

??前面给大家介绍了SpringBoot启动的核心流程,本文开始给大家详细的来介绍SpringBoot启动中的具体实现的相关细节 。

springboot源码深度解析 springboot源码怎么看

文章插图
SpringBoot2.png
SpringApplication构造器
??首先我们来看下在SpringApplication的构造方法中是如何帮我们完成这4个核心操作的 。
image.png
1@SuppressWarnings({ \\”unchecked\\”, \\”rawtypes\\” }) 2public SpringApplication(ResourceLoader resourceLoader, Class… primarySources) { 3// 传递的resourceLoader为null 4this.resourceLoader = resourceLoader; 5Assert.notNull(primarySources, \\”PrimarySources must not be null\\”); 6// 记录主方法的配置类名称 7this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); 8// 记录当前项目的类型 9this.webApplicationType = WebApplicationType.deduceFromClasspath();10// 加载配置在spring.factories文件中的ApplicationContextInitializer对应的类型并实例化11// 并将加载的数据存储在了 initializers 成员变量中 。12setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));13// 初始化监听器 并将加载的监听器实例对象存储在了listeners成员变量中14setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));15// 反推main方法所在的Class对象 并记录在了mainApplicationClass对象中16this.mainApplicationClass = deduceMainApplicationClass();17}1.webApplicationType
??首先来看下webApplicationType是如何来推导出当前启动的项目的类型 。通过代码可以看到是通过deduceFromClassPath()方法根据ClassPath来推导出来的 。
1this.webApplicationType = WebApplicationType.deduceFromClasspath();
??跟踪进去看代码
【springboot源码深度解析 springboot源码怎么看】在看整体的实现逻辑之前,我们先分别看两个内容,第一就是在上面的代码中使用到了相关的静态变量 。
image.png
??这些静态变量其实就是一些绑定的Java类的全类路径 。第二个就是 ClassUtils.isPresent()方法,该方法的逻辑也非常简单,就是通过反射的方式获取对应的类型的Class对象,如果存在返回true,否则返回false
image.png
??所以到此推导的逻辑就非常清楚了
image.png
2.setInitializers
??然后我们再来看下如何实现加载初始化器的 。
1// 加载配置在spring.factories文件中的ApplicationContextInitializer对应的类型并实例化2// 并将加载的数据存储在了 initializers 成员变量中 。3setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
??首先所有的初始化器都实现了ApplicationContextInitializer接口,也就是根据这个类型来加载相关的实现类 。
?然后加载的关键方法是getSpringFactoriesInstances()方法 。该方法会加载 spring.factories文件中的key为org.springframework.context.ApplicationContextInitializer 的值 。
spring-boot项目下
1# Application Context Initializers2org.springframework.context.ApplicationContextInitializer=3org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,4org.springframework.boot.context.ContextIdApplicationContextInitializer,5org.springframework.boot.context.config.DelegatingApplicationContextInitializer,6org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,7org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
spring-boot-autoconfigure项目下
1# Initializers2org.springframework.context.ApplicationContextInitializer=3org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,4org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
image.png
具体的加载方法为 `getSpringFacotiesInstance()`方法,我们进入查看
??先进入SpringFactoriesLoader.loadFactoryNames(type, classLoader)中具体查看加载文件的过程.
image.png
??然后我们来看下 loadSpringFactories方法
image.png
??通过Debug的方式查看会更清楚哦
image.png
??通过 loadSpringFactories 方法我们看到把 spring.factories文件中的所有信息都加载到了内存中了,但是我们现在只需要加载ApplicationContextInitializer类型的数据 。这时我们再通过 getOrDefault()方法来查看 。
image.png
??进入方法中查看
image.png
??然后会根据反射获取对应的实例对象 。
image.png
image.png
??好了到这其实我们就清楚了getSpringFactoriesInstances方法的作用就是帮我们获取定义在 META-INF/spring.factories文件中的可以为ApplicationContextInitializer 的值 。并通过反射的方式获取实例对象 。然后把实例的对象信息存储在了SpringApplication的 initializers属性中 。