当前位置: 首页 > 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
http://www.lryc.cn/news/129320.html

相关文章:

  • 中间件的介绍
  • LVS-DR模式下(RS检测)ldirectord工具实现部分节点掉点后将请求发往正常设备进行处理
  • c++游戏制作指南(四):c++实现数据的存储和读取(输入流fstream)
  • 如何使用CSS实现一个响应式视频播放器?
  • Typora上传文件到Gitee
  • 系统架构设计师---2017年下午试题1分析与解答(试题三)
  • 从零搭建vue + element-plus 项目
  • 原码、补码、反码
  • 煤矿调度IP语音对讲广播模块一键求助对讲矿用调度通信系统SIP语音对讲求助终端
  • 堆 和 优先级队列(超详细讲解,就怕你学不会)
  • AIGC绘画:基于Stable Diffusion进行AI绘图
  • python实现对Android系统手机亮度的调节
  • 《论文阅读14》FAST-LIO
  • Kotlin CompletableDeferred 入门
  • stm32g070的PD0/PD2 PA8和PB15
  • 【数据结构】 链表简介与单链表的实现
  • 【Leetcode】98. 验证二叉搜索树
  • ViewFs And Federation On HDFS
  • 每日一学——无线基础知识
  • 【腾讯云 Cloud Studio 实战训练营】在线 IDE 编写 canvas 转换黑白风格头像
  • 【Hystrix技术指南】(7)故障切换的运作流程原理分析(含源码)
  • Springboot 整合MQ实现延时队列入门
  • 前端基础(Vue框架)
  • 【实用插件】ArcGIS for AutoCAD插件分享下载
  • GaussDB数据库SQL系列-子查询
  • Kafka 什么速度那么快
  • 环形链表笔记(自用)
  • js循环中发起请求数据不一致问题
  • 工作流自动化:提升效率、节约成本的重要工具
  • 仿牛客论坛项目day7|Kafka