Springboot默认加载application.yml原理以及扩展

SpringApplication.run(…)默认会加载classpath下的application.yml或application.properties配置文件。公司要求搭建的框架默认加载一套默认的配置文件demo.properties,让开发人员实现“零”配置开发,但是前提如果开发人员在application.yml或application.properties文件中自定义配置,则会“覆盖”默认的demo.properties文件,按照Springboot外部化配置的特性(优先使用先加载的),只要demo.properties配置在application.yml或application.properties 配置之后加载到environment中即可。

一、SpirngApplication.run(…)源码分析

通过源码分析,得知Springboot加载配置文件,是利用Spring的事件机制,通过EventPublishingRunListener取发布准备资源事件ApplicationEnvironmentPreparedEvent,被ConfigFileApplicationListener监听到,从而来实现资源的加载

具体源码如下:

    public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();//这里是扩展的关键点SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//这里是加载资源的关键ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);....}
//从方法名称来看就是准备environment的即配置信息
   private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environmentConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());//这里默认EventPublishingRunListener发布ApplicationEnvironmentPreparedEvent事件//让监听器ConfigFileApplicationListener加载配置文件//这个listeners就是我们扩展的地方listeners.environmentPrepared(environment);bindToSpringApplication(environment);if (this.webApplicationType == WebApplicationType.NONE) {environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}ConfigurationPropertySources.attach(environment);return environment;}
SpirngApplication.run(...)方法中有个重要的扩展点方法getRunListeners(args);private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}//可扩展的关键点SpringFactoriesLoader//SpringFactoriesLoader会去加载META-INF/spring.factories文件,并根据//type过滤出符合要求的类//比如这里的type对应的是:SpringApplicationRunListenerprivate <T> Collection<T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}

Springboot默认提供的META-INF/spring.factories,这里就是我们可以扩展的地方

Run Listeners

org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

至此资源加载的大概流程就分析完了,下面是我们的扩展

二、扩展——自定义加载配置文件(demo.properties)

通过上述源码分析得知:只需要在项目中添加META-INF/spring.factories,并配置SpringApplicationRunListener为我们自定义的来即可

1、在项目中的resources下创建META-INF/spring.factories

org.springframework.boot.SpringApplicationRunListener=\
com.demo.module.ApplicatonEnvironDemoListener

2、ApplicatonEnvironDemoListener的代码

  package com.chyjr.hyboot.demo.module;import org.springframework.boot.SpringApplication;import org.springframework.boot.SpringApplicationRunListener;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.core.PriorityOrdered;import org.springframework.core.env.ConfigurableEnvironment;import org.springframework.core.env.MutablePropertySources;import org.springframework.core.env.PropertiesPropertySource;import org.springframework.core.env.PropertySource;import java.io.IOException;import java.util.Properties;public class ApplicatonEnvironDemoListener implements SpringApplicationRunListener,PriorityOrdered {private SpringApplication application;private String[] args;/*** 通过反射创建该实例对象的,构造方法中的参数要加上如下参数*/public ApplicatonEnvironDemoListener(SpringApplication application,String[] args){this.application = application;this.args = args;}/*** 在准备环境之间调用* SpringApplication#run -> listeners.starting();*/@Overridepublic void starting() {System.out.println("starting-----");}@Overridepublic void environmentPrepared(ConfigurableEnvironment environment) {Properties properties = new Properties();try {//demo.properties就是我们自定义的配置文件,extension是自定义目录properties.load(this.getClass().getClassLoader().getResourceAsStream("extension/demo.properties"));PropertySource propertySource =new PropertiesPropertySource("demo",properties);//PropertySource是资源加载的核心MutablePropertySources propertySources = environment.getPropertySources();//这里添加最后propertySources.addLast(propertySource);} catch (IOException e) {e.printStackTrace();}}//省略其他方法.../*** 这里可以设置该配置文件加载的顺序,在application.yml之前还是之后* EventPublishingRunListener#getOrder方法返回 “0”,按照需求这里我们这是比0大,* 即在application.yml之后加载,这样在application.yml配置时,可以“覆盖”my.yml* 这里用“覆盖”可能不合适,意思到了就好*/@Overridepublic int getOrder() {return 1;}}

Springboot默认加载application.yml原理相关推荐

  1. SpringBoot启动如何加载application.yml配置文件

    一.前言 在spring时代配置文件的加载都是通过web.xml配置加载的(Servlet3.0之前),可能配置方式有所不同,但是大多数都是通过指定路径的文件名的形式去告诉spring该加载哪个文件: ...

  2. spring boot实战(第六篇)加载application资源文件源码分析

    前言 在上一篇中了解了spring配置资源的加载过程,本篇在此基础上学习spring boot如何默认加载application.xml等文件信息的. ConfigFileApplicationLis ...

  3. springboot 配置文件加载顺序 与boboootStrap属性文件对比

    spring boot 启动时 会扫描 以下位置的 application.properties 或者 yml 作为默认配置文件 file:./config/ file:./ classpath:/c ...

  4. SpringBoot - 配置文件加载位置与优先级

    SpringBoot - 配置文件加载位置与优先级 [1]项目内部配置文件 spring boot 启动会扫描以下位置的application.properties或者application.yml文 ...

  5. SpringBoot热加载实现与类加载浅谈

    SpringBoot热加载实现与类加载浅谈 热部署与热加载: 热部署和热加载都是基于类加载器实现的,热加载是服务器监听class等文件的改变然后对改变的文件进行局部加载,所以不会删除session,也 ...

  6. springboot配置文件加载顺序_「SpringBoot系列」配置文件加载优先级解析

    SpringBoot提供了外部分配置功能,可以使用属性文件(properties).YAML(yml)文件.环境变量和命令行参数来进行处部参数配置,并t以特定的顺序来处理配置,以便于允许合理的覆盖值. ...

  7. springboot log4j2.xml读取application.yml中的属性值

    注意:部份代码太长,可以通过文末的图片快速查看对应位置 项目需求 用户想自己配置日志存放的位置,因此我们需要满足提供可以配置的文件,用以满足用户的需求. 因此,我们主要通过 log4j2.xml 来读 ...

  8. SpringBoot配置加载顺序

    文章目录 前言 一.Spring Boot 配置优先级 二.命令行参数 示例 1 配置文件 示例 2 三.示例分析 前言 Spring Boot 不仅可以通过配置文件进行配置,还可以通过环境变量.命令 ...

  9. JVM源码阅读-本地库加载流程和原理

    前言 本文主要研究OpenJDK中JVM源码中涉及到native本地库的加载流程和原理的部分.主要目的是为了了解本地库是如何被加载到虚拟机,以及是如何找到并执行本地库里的本地方法,以及JNI的 JNI ...

最新文章

  1. mc服务器村民交易修改,【原创】【教程】MCPE自定义村民交易内容
  2. mysql子查询字符串位置_MySql基础-子查询
  3. 01_Linux系统系统语言查询,设置Xshell工具,中文显示,测试Xshell中文字符显示,Linux中文显示乱码设置
  4. ***从菜鸟到大虾教程下载
  5. 【web前端优化】前端无优化,庸人自扰之!
  6. python eval简介
  7. 当子元素用position:relative;时,父元素的overflow:hidden;在ie中失效的解决办法
  8. Flutter实战一Flutter聊天应用(二)
  9. 华三 h3c ACL配置
  10. html编写注册页面
  11. Windows 域时间同步
  12. 古代一些练外丹的资料
  13. unity3D游戏开发一之初识unity
  14. 2013蓝桥杯 CC++程序设计本科B组 第39级台阶
  15. java启动绑定网卡_ServerSocket 默认邦定IP
  16. ChinaSoft 论坛巡礼 | 泛在操作系统理论、技术与开源生态构建
  17. PDF文档翻译中文的方法
  18. 【高性能计算】HPC概述
  19. Java编程输入学员小明3门课程成绩,编写程序实现
  20. leetcode971. 翻转二叉树以匹配先序遍历

热门文章

  1. UART协议驱动设计
  2. java自我介绍_JAVA面试技巧之自我介绍
  3. python po设计模式_(Python)PO设计模式
  4. 系统业务逻辑书籍_「樊登读书会强推:免费送10本绝密书」彻底改变你的逻辑思维能力...
  5. c语言将字母的acsaii,C语言上机实验 答案
  6. mysql innodb myisam 混合,MySQL MyIsam/InnoDB混合在一起的事务
  7. php8vsgo,vscode编辑好go语言代码要怎么运行
  8. python -pass的用法
  9. 【CF global1 D / CF1110D】 Jongmah
  10. 【IT界的厨子】酱香鲈鱼