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

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

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

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

SpringBoot2.png

SpringApplication构造器

  首先我们来看下在SpringApplication的构造方法中是如何帮我们完成这4个核心操作的。

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

image.png

1 @SuppressWarnings({ \"unchecked\", \"rawtypes\" })
2 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
3 // 传递的resourceLoader为null
4 this.resourceLoader = resourceLoader;
5 Assert.notNull(primarySources, \"PrimarySources must not be null\");
6 // 记录主方法的配置类名称
7 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
8 // 记录当前项目的类型
9 this.webApplicationType = WebApplicationType.deduceFromClasspath();
10 // 加载配置在spring.factories文件中的ApplicationContextInitializer对应的类型并实例化
11 // 并将加载的数据存储在了 initializers 成员变量中。
12 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
13 // 初始化监听器 并将加载的监听器实例对象存储在了listeners成员变量中
14 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
15 // 反推main方法所在的Class对象 并记录在了mainApplicationClass对象中
16 this.mainApplicationClass = deduceMainApplicationClass();
17 }

1.webApplicationType

  首先来看下webApplicationType是如何来推导出当前启动的项目的类型。通过代码可以看到是通过deduceFromClassPath()方法根据ClassPath来推导出来的。

1this.webApplicationType = WebApplicationType.deduceFromClasspath();

  跟踪进去看代码

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

在看整体的实现逻辑之前,我们先分别看两个内容,第一就是在上面的代码中使用到了相关的静态变量。

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

image.png

  这些静态变量其实就是一些绑定的Java类的全类路径。第二个就是 ClassUtils.isPresent()方法,该方法的逻辑也非常简单,就是通过反射的方式获取对应的类型的Class对象,如果存在返回true,否则返回false

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

image.png

  所以到此推导的逻辑就非常清楚了

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

image.png

2.setInitializers

  然后我们再来看下如何实现加载初始化器的。

1// 加载配置在spring.factories文件中的ApplicationContextInitializer对应的类型并实例化
2 // 并将加载的数据存储在了 initializers 成员变量中。
3 setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

  首先所有的初始化器都实现了
ApplicationContextInitializer接口,也就是根据这个类型来加载相关的实现类。

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

 然后加载的关键方法是
getSpringFactoriesInstances()方法。该方法会加载 spring.factories文件中的key为
org.springframework.context.ApplicationContextInitializer 的值。

spring-boot项目下

1# Application Context Initializers
2org.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# Initializers
2org.springframework.context.ApplicationContextInitializer=
3org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,
4org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

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

image.png

具体的加载方法为 `getSpringFacotiesInstance()`方法,我们进入查看

  先进入
SpringFactoriesLoader.loadFactoryNames(type, classLoader)中具体查看加载文件的过程.

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

image.png

  然后我们来看下 loadSpringFactories方法

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

image.png

  通过Debug的方式查看会更清楚哦

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

image.png

  通过 loadSpringFactories 方法我们看到把 spring.factories文件中的所有信息都加载到了内存中了,但是我们现在只需要加载
ApplicationContextInitializer类型的数据。这时我们再通过 getOrDefault()方法来查看。

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

image.png

  进入方法中查看

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

image.png

  然后会根据反射获取对应的实例对象。

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

image.png

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

image.png

  好了到这其实我们就清楚了
getSpringFactoriesInstances方法的作用就是帮我们获取定义在 META-INF/spring.factories文件中的可以为
ApplicationContextInitializer 的值。并通过反射的方式获取实例对象。然后把实例的对象信息存储在了SpringApplication的 initializers属性中。

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

image.png

3.setListeners

  清楚了 setInitializers()方法的作用后,再看 setListeners()方法就非常简单了,都是调用了
getSpringFactoriesInstances方法,只是传入的类型不同。也就是要获取的 META-INF/spring.factories文件中定义的不同信息罢了。

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

image.png

  即加载定义在 META-INF/spring.factories文件中声明的所有的监听器,并将获取后的监听器存储在了 SpringApplication的 listeners属性中。

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

image.png

  默认加载的监听器为:

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

image.png

4.mainApplicationClass

  最后我们来看下
duduceMainApplicaitonClass()方法是如何反推导出main方法所在的Class对象的。通过源码我们可以看到是通过 StackTrace来实现的。

1StackTrace:
2我们在学习函数调用时,都知道每个函数都拥有自己的栈空间。
3一个函数被调用时,就创建一个新的栈空间。那么通过函数的嵌套调用最后就形成了一个函数调用堆栈

  StackTrace其实就是记录了程序方法执行的链路。通过Debug方式可以更直观的来呈现。

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

image.png

  那么相关的调用链路我们都可以获取到,剩下的就只需要获取每链路判断执行的方法名称是否是 main就可以了。

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

image.png

  好了到此相关的4个核心步骤就给大家分析完了,希望对大家能有所帮助哦!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 55@qq.com 举报,一经查实,本站将立刻删除。转转请注明出处:https://www.szhjjp.com/n/85607.html

(0)
nan
上一篇 2022-01-15
下一篇 2022-01-15

相关推荐

  • 星巴克月饼兑换券丢了怎么办(星巴克月饼券不见了怎么办)

    星巴克月饼是比较受欢迎的一个品牌月饼,它每年都会上市好几款不同口味不同价格的月饼礼盒,可以满足不同人的需求。星巴克月饼一般都会有礼品券,可以提前预约上门取货,但是如果兑换券不小心丢失了,大多可能就取不了货了。星巴克月饼兑

    2021-09-03
    0
  • 鼠标宏怎么设置连点速度(win10自带鼠标连点器)

    相信看了上一期的朋友一定对鼠标宏有一些了自己的理解,同时各位在浏览各类攻略帖子时,都会或多或少的看见“宏”这个字眼,其实这只是可以使得我们的游戏体验更好,那么具体的操作大家还是有很多疑惑,那我今天给大家详细的讲解有关鼠标宏的原理。一、鼠标宏的简单介绍

    2021-11-10 科技
    0
  • 手把手j教你Win10不支持独立音量调整(win10音量快捷键)

    Win10改进了原有的音量调节滑杆,由之前的竖版改为横版,还增加了半透明特效。漂亮是漂亮了,可一个问题是,它取消了原来的独立音量调节。也就是说当你把QQ音量调大后,酷狗也会跟着变大,很多时候显得十分不便。其实这个问题并不难解决,接下来小编

    2021-12-11 科技
    0
  • 2022年买房还是2025年买房(2022年还适合买房吗)

    2021年其实已经到了下半年了,很多购房者其实还是在观望当中,想知道接下来的几年房价会是什么样的变化,有人说2022年房价会下跌,也有人说未来3年房价都会有涨跌,那么究竟是2022年买房还是2025年买房,2022年还适合买房吗,那么接下来大家就随久久派小编一

    2021-09-09
    0
  • Excel数值取整的九种方式(excel取整数公式)

    数据取整,是EXCEL数据处理的最常用的方式。可能大家最经常用的是INT函数,但,INT函数并不能满足所有的取整要求。比如,今天一位朋友要按照某位数的倍数取整,INT就解决不了了。小编总结各种取整函数,遇到不同的取整要求,可以翻出来找合

    2021-12-11 科技
    0
  • sfp模块拆解(sfp光模块使用方法)

    在光纤网络中,10G光模块凭借着较低的成本和功耗被广泛应用于学校、公司等应用环境中。XFP和SFP+是10G光模块常见的两种封装类型,下面易天光通信(ETU-LINK)就为大家介绍下XFP与SFP+光模块的区别是什么?以及它们两者能相互连接吗?1、X

    2021-10-23
    0

发表回复

登录后才能评论