当前位置: 首页 > news >正文

003-Spring boot 启动流程分析

目录

    • 启动流程分析
      • 创建 SpringApplication
      • 启动 run(String... args)
    • 读取配置流程分析
      • listeners.environmentPrepared
        • 解析配置文件详细分析
        • EnvironmentPostProcessor 详细分析

启动流程分析

SpringApplication.run(App.class, args);return new SpringApplication(primarySources).run(args);

创建 SpringApplication

SpringApplication(primarySources):this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//这个推断流程 001 篇 分析webServer里有详情 web应用返回WebApplicationType.SERVLET
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//获取Factories中配置的 BootstrapRegistryInitializer
this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
this.initializers = getSpringFactoriesInstances(ApplicationContextInitializer.class);
this.listeners = getSpringFactoriesInstances(ApplicationListener.class));
//推断main方法所在的Class
this.mainApplicationClass = deduceMainApplicationClass();

启动 run(String… args)

//获取Factories中配置的 SpringApplicationRunListener 并执行其 starting()
SpringApplicationRunListeners listeners = getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args).forEach(listener.starting(bootstrapContext))
//封装 args:这里会读取执行jar的时候添加的以 '--' 开头的 kay=value
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//读取配置 包括:系统,JVM,ServletContext,properties,yaml配置
//全部设置到 environment 中
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
//这一步我查资料应该是忽略Java解析BeanInfo的缓存 因为Spring使用的是ASM技术
configureIgnoreBeanInfo(environment);
//打印banner并返回
Banner printedBanner = printBanner(environment);
//根据类型返回上下文 001 有详细分析 AnnotationConfigServletWebServerApplicationContext
context = createApplicationContext();
context.applicationStartup = applicationStartup;
//利用ApplicationContextInitializer初始化Spring 上下文
//发布ApplicationContextInitializedEvent
//注册primarySources = run() 传入的配置类列表
//发布ApplicationContextPreparedEvent
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
//调用refresh(context) 这一步就是执行Spring bean创建的逻辑了
refreshContext(context);
//这一步是空的 给子类一个实现的机会
afterRefresh(context, applicationArguments);
//遍历执行之前 listeners started()
listeners.started(context, timeTakenToStartup);
//执行 ApplicationRunner.run(args);
//执行 CommandLineRunner.run(args.getSourceArgs());
//两个执行器只有 入参的区别 一个是解析之后的对象,一个是字符串
callRunners(context, applicationArguments);
//遍历执行之前 listeners ready()
listeners.ready(context, timeTakenToReady);

读取配置流程分析

//读取配置 包括:系统,JVM,ServletContext,properties,yaml配置
//全部设置到 environment 中
prepareEnvironment(listeners, bootstrapContext, applicationArguments)://new ApplicationServletEnvironment();
//默认带有配置名称 
//servletConfigInitParams 内容为空
//servletContextInitParams 内容为空
//systemProperties 内容为各种系统配置 如 java 版本、 -D开头的参数、OS版本等等
//systemEnvironment 内容为系统环境变量里的内容 如:JAVA_HOME、PATH等等
ConfigurableEnvironment environment = getOrCreateEnvironment();
//放入一个name:commandLineArgs
//解析 cmd 执行jar的时候带有的参数 就是 .jar 后配置的 不带 -D的 
//解析后放入 new SimpleCommandLinePropertySource(args) 并放在第一个
//SimpleCommandLinePropertySource 有两个属性 
//optionArgs 中放的是 带有 -- 的 key=value形式的参数 已经解析好了
//nonOptionArgs 中放的是 不带 -- 的参数 原样放进
configureEnvironment(environment, applicationArguments.getSourceArgs());
//设置到第一个 name:configurationProperties
//把 environment.getPropertySources() 设置进去
ConfigurationPropertySources.attach(environment);// 执行 EventPublishingRunListener#environmentPrepared
// 其实就发布了new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment))事件
// spring中的事件就是直接调用 所有的监听器  getListeners.froEach()
// 下边详细分析
listeners.environmentPrepared(bootstrapContext, environment);//绑定environment 到 SpringApplication
bindToSpringApplication(environment);//有可能是new出来的新的设置 到第一个 name:configurationProperties
ConfigurationPropertySources.attach(environment);

listeners.environmentPrepared

// 获取所有监听了 ApplicationEnvironmentPreparedEvent事件的监听器
EnvironmentPostProcessorApplicationListenerEnvironmentPostProcessor#postProcessEnvironment(environment, application)
AnsiOutputApplicationListener
LoggingApplicationListener
BackgroundPreinitializer
DelegatingApplicationListener
FileEncodingApplicationListener
getApplicationListeners(event, type)

解析配置文件详细分析

EnvironmentPostProcessorApplicationListener 中

// EnvironmentPostProcessor 序号 有:
// CloudFoundryVcapEnvironmentPostProcessor Ordered.HIGHEST_PRECEDENCE + 9
// ConfigDataEnvironmentPostProcessor Ordered.HIGHEST_PRECEDENCE + 10
// RandomValuePropertySourceEnvironmentPostProcessor Ordered.HIGHEST_PRECEDENCE + 1
// SpringApplicationJsonEnvironmentPostProcessor Ordered.HIGHEST_PRECEDENCE + 5
// SystemEnvironmentPropertySourceEnvironmentPostProcessor Ordered.HIGHEST_PRECEDENCE + 4
// DebugAgentEnvironmentPostProcessor Ordered.LOWEST_PRECEDENCE
// IntegrationPropertiesEnvironmentPostProcessor Ordered.LOWEST_PRECEDENCE
for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),event.getBootstrapContext())) {postProcessor.postProcessEnvironment(environment, application);
}

EnvironmentPostProcessor 详细分析

按排序逐个执行

1. 
RandomValuePropertySourceEnvironmentPostProcessor 
添加一个 name为 random 的 RandomValuePropertySource 自动根据 getProperty(random.long)的类型返回随机数2.
SystemEnvironmentPropertySourceEnvironmentPostProcessor 
这个就是把 systemEnvironment 内容重新包装成一个带有 prefix 字段的对象 具体有啥用没找到3.
SpringApplicationJsonEnvironmentPostProcessor 
对 spring.application.json 和 SPRING_APPLICATION_JSON 配置进行JSON解析 这个解析比较早所以放在一般的配置文件里解析不到4.
CloudFoundryVcapEnvironmentPostProcessor 
处理云服务器上的 VCAP_APPLICATION and VCAP_SERVICES JOSN变量 转化为 vcap.application. 或 vcap.services.开头的配置5.
ConfigDataEnvironmentPostProcessor 
包含了2组解析路径  
第一组> file:./;optional:file:./config/;optional:file:./config/*/
*/
第二组> optional:classpath:/;optional:classpath:/config/
遍历调用: 
{StandardConfigDataLocationResolver} 文件名:spring.config.name 没有读取默认 application0 = {PropertiesPropertySourceLoader}  文件后缀:properties、xml1 = {YamlPropertySourceLoader}  文件后缀:yml、yaml
在解析的时候就现根据路径和文件名称文件后缀组成文件路径 20(默认情况下:1个文件名 * 4中文件后缀 * 5个解析路径 = 20): classpath:/application.properties, classpath:/application.yaml
挨个判断文件是否存在
存在的文件再解析内容6.
IntegrationPropertiesEnvironmentPostProcessor 
处理 META-INF/spring.integration.properties 中指定的配置
已经规定好了解析的Key7.
DebugAgentEnvironmentPostProcessor
解析调试代理配置 spring.reactor.debug-agent.enabled

相关文章:

003-Spring boot 启动流程分析

目录 启动流程分析创建 SpringApplication启动 run(String... args) 读取配置流程分析listeners.environmentPrepared解析配置文件详细分析EnvironmentPostProcessor 详细分析 启动流程分析 SpringApplication.run(App.class, args);return new SpringApplication(primarySour…...

中间件的介绍

1.1 什么是中间件 中间件是介于应用系统和系统软件之间的一类软件&#xff0c;他使用系统软件所提供的基础服务&#xff0c;衔接网络上应用系统的各个部分或不同的应用&#xff0c;能够达到资源共享、功能共享的目的。 例如MySQL就可以看作是具备中间件特性的一种技术&#x…...

LVS-DR模式下(RS检测)ldirectord工具实现部分节点掉点后将请求发往正常设备进行处理

基于前文的LVS-DR集群构建环境 一.下载ldirectord软件 二.将模板文件中的LVS-DR模式相关文件拷贝到/etc/ha.d主配置目录并按实际设备修改 三.配置两台RS匹配规则 四.停止RS1的http服务进行测试 RS1失去工作能力&#xff0c;RS2接替RS1 基于前文的LVS-DR集群构建环境 一.下…...

c++游戏制作指南(四):c++实现数据的存储和读取(输入流fstream)

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f35f;欢迎来到静渊隐者的csdn博文&#xff0c;本文是c游戏制作指南的一部&#x1f35f; &#x1f355;更多文章请点击下方链接&#x1f355; &#x1f368; c游戏制作指南&#x1f3…...

如何使用CSS实现一个响应式视频播放器?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现响应式视频播放器⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣…...

Typora上传文件到Gitee

工作内容,不对外开放 一、Typora上传笔记到CSDN 一、安装node.js 官网链接:Node.js (nodejs.org) 下载后得到一个.msi文件,双击即可。 win + R 打开CMD,基于node -v 和npm -v,验证是否安装成功: 二、配置Gitee 1、新建仓库 2、开源此仓库 2.1、初始化readme文件...

系统架构设计师---2017年下午试题1分析与解答(试题三)

2017年下午试题1分析与解答 试题三 阅读以下关于机器人操作系统架构的描述,回答问题1至问题3 【说明】 随着人工智能技术的发展,工业机器人已成为当前工业界的热点研究对象。某宇航设备公司为了扩大业务范围,决策层研究决定准备开展工业机器人研制新业务。公司将论证工作…...

从零搭建vue + element-plus 项目

目录 从零搭建vue element-plus 项目 环境安装 安装项目 安装命令如下&#xff1a; 选择配置如下&#xff1a; 安装插件与启动服务 安装element框架 使用element框架 测试element是否安装成功 环境判断 安装插件 使用插件 配置变量 暴漏变量 测试…...

原码、补码、反码

一、前置概念 计算机底层存储数据时使用的是二进制数字&#xff0c;但是计算机在存储一个数字时并不是直接存储该数字对应的二进制数字&#xff0c;而是存储该数字对应二进制数字的补码。所以接下来我们需要来了解一下原码、反码和补码。 那么再了解原码、反码、补码之前&…...

煤矿调度IP语音对讲广播模块一键求助对讲矿用调度通信系统SIP语音对讲求助终端

硬件接口描述 SV-2101VP/ SV-2103VP系列网络音频模块&#xff0c;所有外部连接采用端子&#xff0c;电源采用2.0mm的端子&#xff0c;网络采用标准RJ45连接器&#xff0c;其他都是1.25mm的连接器。 端口类型定义 P ———— 电源 AI ———— 模拟输入&#xff08;在这里是音…...

堆 和 优先级队列(超详细讲解,就怕你学不会)

优先级队列 一、堆的概念特性二、堆的创建1、向下调整算法2、向下调整建堆3、向下调整建堆的时间复杂度 三、堆的插入1、向上调整算法实现插入2、插入创建堆的时间复杂度 三、堆的删除四、Java集合中的优先级队列1、PriorityQueue 接口概述及模拟实现2、如何创建大根堆&#xf…...

AIGC绘画:基于Stable Diffusion进行AI绘图

文章目录 AIGC深度学习模型绘画系统stable diffusion简介stable diffusion应用现状在线网站云端部署本地部署Stable Diffusion AIGC深度学习模型绘画系统 stable diffusion简介 Stable Diffusion是2022年发布的深度学习文本到图像生成模型&#xff0c;它主要用于根据文本的描述…...

python实现对Android系统手机亮度的调节

要实现对手机亮度的调节&#xff0c;需要使用Android系统的API。以下是一个简单的Python代码示例&#xff0c;演示如何使用ADB工具和Python脚本来控制Android设备的亮度&#xff1a; from adb.client import Client as AdbClient import os# 连接设备 client AdbClient(host&…...

《论文阅读14》FAST-LIO

一、论文 研究领域&#xff1a;激光雷达惯性测距框架论文&#xff1a;FAST-LIO: A Fast, Robust LiDAR-inertial Odometry Package by Tightly-Coupled Iterated Kalman Filter IEEE Robotics and Automation Letters, 2021 香港大学火星实验室 论文链接论文github 二、论文概…...

Kotlin CompletableDeferred 入门

在 Kotlin 中&#xff0c;CompletableDeferred 是一个用于异步编程的类&#xff0c;它提供了一种实现异步操作和等待操作结果的方式。 CompletableDeferred 是 Deferred 接口的具体实现之一&#xff0c;可以用于表示一个可能会在将来完成的操作。它提供了以下主要功能&#xf…...

stm32g070的PD0/PD2 PA8和PB15

目前在用STM32G070做项目&#xff0c;其中PD2TIMER3去模拟PWM&#xff0c;PD0用作按键检测&#xff0c;测试发现PD0低电平检测没有问题&#xff0c;高电平检测不到&#xff0c;电路图如下图所示&#xff1a; 用万用表测试电平&#xff0c;高电平1.0V左右&#xff0c;首先怀疑硬…...

【数据结构】 链表简介与单链表的实现

文章目录 ArrayList的缺陷链表链表的概念及结构链表的分类单向或者双向带头或者不带头循环或者非循环 单链表的实现创建单链表遍历链表得到单链表的长度查找是否包含关键字头插法尾插法任意位置插入删除第一次出现关键字为key的节点删除所有值为key的节点回收链表 总结 ArrayLi…...

【Leetcode】98. 验证二叉搜索树

一、题目 1、题目描述 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。示例1: 输入:root = …...

ViewFs And Federation On HDFS

序言 ViewFs 是在Federation的基础上提出的,用于通过一个HDFS路径来访问多个NameSpace,同时与ViewFs搭配的技术是client-side mount table(这个就是具体的规则配置信息可以放置在core.xml中,也可以放置在mountTable.xml中). 总的来说ViewFs的其实就是一个中间层,用于去连接不…...

每日一学——无线基础知识

无线局域网&#xff08;Wireless Local Area Network&#xff0c;简称 WLAN&#xff09;是一种使用无线通信技术连接多个无线终端设备的局域网。它通常基于无线电波传输数据&#xff0c;并使用无线接入点&#xff08;Access Point&#xff0c;简称 AP&#xff09;来连接无线设备…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

门静脉高压——表现

一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构&#xff1a;由肠系膜上静脉和脾静脉汇合构成&#xff0c;是肝脏血液供应的主要来源。淤血后果&#xff1a;门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血&#xff0c;引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...

Django RBAC项目后端实战 - 03 DRF权限控制实现

项目背景 在上一篇文章中&#xff0c;我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统&#xff0c;为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...