Springboot默认加载application.yml原理以及扩展
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 environment
ConfigurableEnvironment 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对应的是:SpringApplicationRunListener
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<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();
*/
@Override
public void starting() {
System.out.println("starting-----");
}
@Override
public 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
* 这里用“覆盖”可能不合适,意思到了就好
*/
@Override
public int getOrder() {
return 1;
}
}
Springboot默认加载application.yml原理以及扩展的更多相关文章
- SpringBoot启动如何加载application.yml配置文件
一.前言 在spring时代配置文件的加载都是通过web.xml配置加载的(Servlet3.0之前),可能配置方式有所不同,但是大多数都是通过指定路径的文件名的形式去告诉spring该加载哪个文件: ...
- springboot加载application.yml文件null
话不多说,直接上代码 本人项目为maven项目 以下是项目结构 pom.xml文件 <?xml version="1.0" encoding="UTF-8" ...
- SpringBoot之加载自定义配置文件
SpringBoot默认加载配置文件名为:application.properties和application.yml,如果需要使用自定义的配置文件,则通过@PropertySource注解指定. J ...
- Eclipse下SpringBoot没有自动加载application.properties文件
Eclipse内创建SpringBoot项目,在java/main/resources文件夹下面创建application.properties配置文件,SpringApplication.run后发 ...
- 使用IDEA开发SpringBoot不加载application.yml配置文件的解决方案
1.如果启动项目不加载application.yml配置文件,那么请确认下是否应用了Resources为项目资源文件夹 2.如果项目起初是可以正常使用的,突然不知道改了什么,然后进行启动项目的时候不加 ...
- SpringBoot配置(1) 配置文件application&yml
SpringBoot配置(1) 配置文件application&yml 一.配置文件 1.1 配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的. application ...
- springboot配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件 –file:./config/ – ...
- SpringBoot系列——加载自定义配置文件
前言 SpringBoot启动时默认加载bootstrap.properties或bootstrap.yml(这两个优先级最高).application.properties或application. ...
- SpringBoot配置文件加载位置与优先级
1. 项目内部配置文件 spring boot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件 –fil ...
随机推荐
- Linux自学系列 -- 常用指令的使用
1.查看目录下内容>ls //列出目录下的文件信息>ls -l //以“详细信息"查看目录文件>ls -a //查看目录“全部”(包括隐藏文件)文件> ...
- 用Margin还是用Padding?
用margin还是用padding这个问题是每个学习CSS进阶时的必经之路. CSS边距属性定义元素周围的空间.通过使用单独的属性,可以对上.右.下.左的外边距进行设置.也可以使用简写的外边距属性同时 ...
- Java获取当前服务器IP实现
package hope.ipaddress.demo; import java.net.InetAddress; import java.net.NetworkInterface; import j ...
- 【bzoj1179】[Apio2009]Atm Tarjan缩点+Spfa最长路
题目描述 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每 ...
- POJ 3461Oulipo KMP模板
KMP之所以线性,因为匹配的时候i是不往回走的 我们只用调整j的位置 假设在s中找t 用二元组(i,j)表示s串的[i-j+1,i] 与t串的[1,j]匹配 假设s[i+1]和t[j]匹配上了,就j+ ...
- C语言fopen函数了解
fopen()函数功能:open a file. 原型:FILE * fopen(const char * path,const char * mode); 需要#include<stdio.h ...
- RQNOJ123_多人背包_C++_Pascal
题目:http://www.rqnoj.cn/problem/123 不得不说,RQNOJ 的机子跑得好慢呀,5*107 的数据范围本地跑 0.2s,服务器上愣是把我卡掉了,最后只好写了一份 Pasc ...
- [LeetCode] Combinations 回溯
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...
- MySQL 5.7主从复制与主主复制实现细节分析
0.简介: MySQL作为世界上使用最为广泛的数据库之一,免费是其原因之一.但不可忽略的是它本身的功能的确很强大.随着技术的发展,在实际的生产环境中,由单台MySQL数据库服务器不能满足实际的需求.此 ...
- loj 数列分块入门 5 7 8
5 题意 给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间开方,区间求和. 思路 用\(tag\)记录这一块是否已全为\(1\). 除分块外,还可用 树状数组+并查集(链表) 或者 线 ...