SpringBoot启动过程源码解析

news2024/10/7 8:25:49

一,构造SpringApplication对象

 1、推测web应用类型

  1. 如果项目依赖中存在org.springframework.web.reactive.DispatcherHandler,并且不存在org.springframework.web.servlet.DispatcherServlet,那么应用类型为WebApplicationType.REACTIVE
  2. 如果项目依赖中不存在org.springframework.web.reactive.DispatcherHandler,也不存在org.springframework.web.servlet.DispatcherServlet,那么应用类型为WebApplicationType.NONE
  3. 否则,应用类型为WebApplicationType.SERVLET

2、获取BootstrapRegistryInitializer对象

  1. 从"META-INF/spring.factories"中读取key为BootstrapRegistryInitializer类型的扩展点,并实例化出对应扩展点对象
  2. BootstrapRegistryInitializer的作用是可以初始化BootstrapRegistry
  3. 上面的DefaultBootstrapContext对象就是一个BootstrapRegistry,可以用来注册一些对象,这些对象可以用在从SpringBoot启动到Spring容器初始化完成的过程中
  4. 没有Spring容器之前就利用BootstrapRegistry来共享一些对象,有了Spring容器之后就利用Spring容器来共享一些对象

3、获取ApplicationContextInitializer对象

  1. 从"META-INF/spring.factories"中读取key为ApplicationContextInitializer类型的扩展点,并实例化出对应扩展点对象。
  2. 顾名思义,ApplicationContextInitializer是用来初始化Spring容器ApplicationContext对象的,比如可以利用ApplicationContextInitializer来向Spring容器中添加ApplicationListener

4、获取ApplicationListener对象

  1. 从"META-INF/spring.factories"中读取key为ApplicationListener类型的扩展点,并实例化出对应扩展点对象
  2. ApplicationListener是Spring中的监听器,并不是SpringBoot中的新概念,不多解释了

5、推测出Main类(main()方法所在的类)

没什么具体的作用,逻辑是根据当前线程的调用栈来判断main()方法在哪个类,哪个类就是Main类

二,run(String... args)方法

1、创建DefaultBootstrapContext对象

2、利用BootstrapRegistryInitializer初始化DefaultBootstrapContext对象

3、获取SpringApplicationRunListeners

4、触发SpringApplicationRunListener的starting()

默认情况下SpringBoot提供了一个EventPublishingRunListener,它实现了SpringApplicationRunListener接口,默认情况下会利用EventPublishingRunListener发布一个ApplicationContextInitializedEvent事件,程序员可以通过定义ApplicationListener来消费这个事件

5、创建Environment对象

Environment对象表示环境变量,该对象内部主要包含了

  1. 当前操作系统的环境变量
  2. JVM的一些配置信息
  3. -D方式所配置的JVM环境变量

6、触发SpringApplicationRunListener的environmentPrepared()

默认情况下会利用EventPublishingRunListener发布一个ApplicationEnvironmentPreparedEvent事件,程序员可以通过定义ApplicationListener来消费这个事件,比如默认情况下会有一个EnvironmentPostProcessorApplicationListener来消费这个事件,而这个ApplicationListener接收到这个事件之后,就会解析application.properties、application.yml文件,并添加到Environment对象中去。

7、打印Banner

8、创建Spring容器对象(ApplicationContext)

会利用ApplicationContextFactory.DEFAULT,根据应用类型创建对应的Spring容器。
ApplicationContextFactory.DEFAULT为

ApplicationContextFactory DEFAULT = (webApplicationType) -> {
    try {
        switch (webApplicationType) {
            case SERVLET:
                return new AnnotationConfigServletWebServerApplicationContext();
            case REACTIVE:
                return new AnnotationConfigReactiveWebServerApplicationContext();
            default:
                return new AnnotationConfigApplicationContext();
        }
    }
    catch (Exception ex) {
        throw new IllegalStateException("Unable create a default ApplicationContext instance, "
                                        + "you may need a custom ApplicationContextFactory", ex);
    }
};

所以

  • 应用类型为SERVLET,则对应AnnotationConfigServletWebServerApplicationContext
  • 应用类型为REACTIVE,则对应AnnotationConfigReactiveWebServerApplicationContext
  • 应用类型为普通类型,则对应AnnotationConfigApplicationContext

9、利用ApplicationContextInitializer初始化Spring容器对象(prepareContext)

默认情况下SpringBoot提供了多个ApplicationContextInitializer,其中比较重要的有ConditionEvaluationReportLoggingListener,别看到它的名字叫XXXListener,但是它确实是实现了ApplicationContextInitializer接口的。

在它的initialize()方法中会:

  1. 将Spring容器赋值给它的applicationContext属性
  2. 并且往Spring容器中添加一个ConditionEvaluationReportListener(ConditionEvaluationReportLoggingListener的内部类),它是一个ApplicationListener
  3. 并生成一个ConditionEvaluationReport对象赋值给它的report属性

ConditionEvaluationReportListener会负责接收ContextRefreshedEvent事件,也就是Spring容器一旦启动完毕就会触发ContextRefreshedEvent,ConditionEvaluationReportListener就会打印自动配置类的条件评估报告。

10、触发SpringApplicationRunListener的contextPrepared()(prepareContext)

默认情况下会利用EventPublishingRunListener发布一个ApplicationContextInitializedEvent事件,默认情况下暂时没有ApplicationListener消费了这个事件

11、调用DefaultBootstrapContext对象的close()(prepareContext)

没什么特殊的,忽略

12、将启动类作为配置类注册到Spring容器中(load()方法)

将SpringApplication.run(MyApplication.class);中传入进来的类,比如MyApplication.class,作为Spring容器的配置类

13、 触发SpringApplicationRunListener的contextLoaded()(prepareContext)

默认情况下会利用EventPublishingRunListener发布一个ApplicationPreparedEvent事件

14、刷新Spring容器(refreshContext)

调用Spring容器的refresh()方法,结合第9、13步,相当于执行了这样一个流程:

  1. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
  2. applicationContext .register(MyApplication.class)
  3. applicationContext .refresh()

15、触发SpringApplicationRunListener的started()

发布ApplicationStartedEvent事件和AvailabilityChangeEvent事件,AvailabilityChangeEvent事件表示状态变更状态,变更后的状态为LivenessState.CORRECT

LivenessState枚举有两个值:

  • CORRECT:表示当前应用正常运行中
  • BROKEN:表示当前应用还在运行,但是内部出现问题,暂时还没发现哪里用到了

16、调用ApplicationRunner和CommandLineRunner

  1. 获取Spring容器中的ApplicationRunner类型的Bean
  2. 获取Spring容器中的CommandLineRunner类型的Bean
  3. 执行它们的run()

17、触发SpringApplicationRunListener的ready()

发布ApplicationReadyEvent事件和AvailabilityChangeEvent事件,AvailabilityChangeEvent事件表示状态变更状态,变更后的状态为ReadinessState.ACCEPTING_TRAFFIC

ReadinessState枚举有两个值:

  • ACCEPTING_TRAFFIC:表示当前应用准备接收请求
  • REFUSING_TRAFFIC:表示当前应用拒绝接收请求,比如Tomcat关闭时,就会发布

AvailabilityChangeEvent事件,并且状态为REFUSING_TRAFFIC

18、上述过程抛异常了就触发SpringApplicationRunListener的failed()

发布ApplicationFailedEvent事件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/543515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【PaLM2】PaLM2 大语言模型与 Bard 使用体验

欢迎关注【youcans的学习笔记】原创作品,火热更新中 【Google I/O 2023】PaLM2 大语言模型与 Bard 使用体验 1. PaLM2 大型语言模型1.1 谷歌发布 PaLM21.2 PaLM2 的功能与性能 2. 基于 PaLM2 的谷歌 AI 产品2.1 智能助手 Duet AI2.2 Gmail:帮我写邮件2.3…

【Spring框架四】——Spring AOP 注解实现和xml方式实现

系列文章目录 【Spring框架一】——Spring框架简介 【Spring框架二】——什么是Spring IOC、 什么是Spring 依赖注入 【Spring框架三】——Spirng IOC和DI的实现 Spring AOP 注解实现和xml方式实现 系列文章目录前言一、什么是Spring AOP(Aspect-Oriented Progra…

OpenAI 宣布推出适用于 iPhone 和 iPad 的 ChatGPT 官方应用程序。

🚀 OpenAI 宣布推出适用于 iPhone 和 iPad 的 ChatGPT 官方应用程序。 OpenAI 宣布推出适用于 iPhone 和 iPad 的 ChatGPT 官方应用程序。 该应用程序具备即时回答各种问题、量身定制的建议、创意灵感、专业意见和个性化学习等功能和特性,可以帮助提高…

【密码产品篇】服务器密码机密钥体系结构

【密码产品篇】服务器密码机密钥体系结构 标准GM/T 0030-2014中规定服务器密码机必须至少支持三层密码体系结构,包括:“管理密钥、用户密钥/设备密钥/密钥加密密钥、会话密钥”。除"管理密钥"外,其他密钥可被用户使用,…

在图片上添加水印的四个方法

如何在图片上添加水印?在当今开放的互联网环境中,平时对于图片的使用已经变成非常广泛,越来越多的人开始关注图片的版权问题。如今,人们越来越注重防盗意识,这是因为我们在网上发布的图片很容易被别有用心之人盗用&…

Maven仓库

1、仓库 仓库:用于存储资源,主要是各种jar包 关于仓库,我们前面讲到了有三种:本地仓库,私服,中央仓库,其中私服和中央仓库都属于远程仓库 中央仓库:maven团队自身维护的仓库&#…

Java面试知识点(全)- Java并发-多线程JUC一

Java面试知识点(全) 导航: https://nanxiang.blog.csdn.net/article/details/130640392 注:随时更新 JUC框架 五个部分: 主要包含: (注意: 网上找的图,主体上可以看出其分类关系也够了) Lock框架和Tools类(把图中这两个放到一起…

一起Linux操作系统部署的Mysql数据库服务器/目录空间占用异常的分析事例

一台Linux操作系统部署的Mysql数据库服务器平时“/"目录占用很低,但每个小时都会出现一次根目录空间占用高的情况,本文系从OS侧对异常事件进行分析排查的过程。 1、初步分析 主机已进行监控,分析监控图表 可见该数据库服务器日常根目录…

王炸功能ChatGPT 联网插件功能放开,视频文章一键变思维导图

就在上周5月13日,Open AI 发文称:“我们将在下周向所有ChatGPT Plus 用户开放联网功能和众多插件”。 这意味着什么? 首先联网功能将使得ChatGPT不再局限于回答2021年9月之前的信息,能直接联网查询最新消息。 而插件功能就可以在…

基于LT6911UXC的LVDS视频接口调试经验

项目方案采用龙讯半导体LT6911系列。 该方案采用HDMI输出转LVDS接口。在本方案中有两种显示屏;一个是10.4寸,一个是15.6寸。分别应 单LVDS与双LVDS接口。 10.4寸屏幕的分辨率为1024*768;单八LVDS信号; 15.6寸的屏幕的分辨率为19…

SSD202D-MIPI屏点亮

调试mipi 点屏参考 - SigmaStarDocs Panel开发参考 - SigmaStarDocs 1.首先要看点屏参考,看懂硬件接线这些原理,然后依据实际的接线配置屏参 和RGB是复用的,所以不一样, 然后配置内核,我是直接编译mipi的内核 2.配置屏参,

如何进行测试分析与设计-HTSM启发式测试策略模型 | 京东云技术团队

测试,没有分析与设计就失去了灵魂; 测试人员在编写用例之前,该如何进行测试分析与设计呢?上次在《测试的底层逻辑》中讲到了【输入输出测试模型】,还讲到了【2W1H测试分析法】,但2W1H分析法是初步的分析方…

Sharding-JDBC分库分表

Sharding-JDBC分库分表 一 分库分表概述 ​ 分库分表,就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分成若干数据库组成,将数据大表拆分为若干数据表组成,使得单一数据库,单一数据表的…

深度学习在语音识别方面的应用

前言 语音识别是一项非常重要的技术,它可以将人类的语音转化为计算机可以理解的形式。深度学习是一种非常强大的机器学习技术,它在语音识别方面也有广泛的应用。本文将详细介绍深度学习在语音识别方面的应用。 语音识别的基本步骤 语音识别的基本步骤包…

KDZD5550系列电压击穿试验仪系统组成

一、产品概述 KDZD5550系列电压击穿试验仪根据国家GB1408.1-2006《绝缘材料电气强度试验方法》其作用可称为电气绝缘强度试验仪、介质强度测试仪等。其工作原理是:把一个高于正常工作的电压加在被测设备的绝缘体上,持续一段规定的时间,加在上…

《软技能:代码以外的生存指南》阅读总结

文章收录: 个人网址:http://linglan01.cn/Github仓库:https://github.com/CatsAndMice/blog/issues 推荐一篇蛮有营养的文章速读《软技能 代码之外的生存指南》。 我比较喜欢实体书籍,所以自己干脆买一本《软技能:代码…

2023年5月DAMA-CDGA/CDGP数据治理认证考试报名

DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业…

c++(类和对象下)

本节目标 1. 再谈构造函数 2. Static成员 3. 友元 4. 内部类 5.匿名对象 6.拷贝对象时的一些编译器优化 7. 再次理解封装 目录 1、再谈构造函数 1.1构造函数体赋值 1.2初始化列表 2 static 成员 2.1概念 2.2特性 3.友元 3.1友元函数 3.2友元类 4.内部类 5匿名对…

甘特图控件DHTMLX Gantt教程:用PHP:Laravel实现Gantt(上)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的大部分开发需求,具备完善的甘特图图表库,功能强大,价格便宜,提供丰富而灵活的JavaScript API接口,与各种服务器端技术&am…

国考省考行测:资料分析:增量减量计算公式,百分数化分数

国考省考行测:增量减量计算公式 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能,附带行测和申论,而常规国考省考最重要的还是申论和行测,所以大家认真准备吧,我讲一起屡屡申论和行测的重要知…