SpringBoot是如何加载配置文件的?
2021-03-11 12:28
标签:tcl 环境 alt meta 一个 com || contain add 本文针对版本2.2.0.RELEASE来分析SpringBoot的配置处理源码,通过查看SpringBoot的源码来弄清楚一些常见的问题比如: SpringBoot加载配置文件的入口是由ApplicationEnvironmentPreparedEvent事件进入的,SpringBoot会在SpringApplication的构造函数中通过spring.factories文件获取ApplicationListener的实例类: spring.factories中有一个ConfigFileApplicationListener类,它会监听ApplicationEnvironmentPreparedEvent然后再加载配置文件 : 有了事件和事件处理的类后,再找出发送事件的地方,就可以搞清楚SpringBoot是怎么加载配置文件的了,SpringBoot在启动之前先初始化好SpringApplicationRunListeners这个类,它会实现SpringApplicationRunListener接口然后对事件进行转发: 获取SpringApplicationRunListeners的代码如下: 同样也会去加载spring.factories文件,该文件有一个EventPublishingRunListener类,该类的作用就是SpringBoot的事件转换成ApplicationEvent发送出去。 上面已经分析到ConfigFileApplicationListener是处理配置文件的主要类,然后进一步的查看SpringBoot是从哪些地址加载配置文件,进入ConfigFileApplicationListener类后会有两个默认的常量: 首先在没有任何配置的情况下,会从DEFAULT_SEARCH_LOCATIONS常量列出来的位置中加载文件名为DEFAULT_NAMES(.properties或yml)的文件,默认位置包括: 它的操作步骤大致如下: SpringBoot的配置支持properties和yaml文件,SpringBoot是如何解析这两种文件的呢,继续分析ConfigFileApplicationListener这个类,里面有个子类叫Loader加载配置文件主要的工作就是由这货负责,但是直接读取properties和yaml并转换成PropertySource还是由里面的PropertySourceLoader负责: 构造Loader对象的时候就会先加载PropertySourceLoader,加载方式还是从spring.factories中读取: 其中配置了两个PropertySourceLoader的实现类: 如果不喜欢properties和yaml这两种格式,想要定义json做为配置文字格式可以直接定义json类型的PropertySourceLoader: 然后在resources目录里面建立个META-INF,再添加个spring.factories里面的内容如下: 最后在resources目录里面建个application.json的配置文件 : 正常启动SpringBoot获取spring.applicaiton.name的配置的值就是JSONConfig: SpringBoot中有个PropertySource接口,专门用来保存属性常见的实现类有: 所有的PropertySource都保存在propertySourceList中,越小的索引优化级越高,所以如果想要覆盖属性只要保证优先级够高就行。 继续分析ConfigFileApplicationListener的Loader子类,在构造时还会创建一个PropertySourcesPlaceholdersResolver,placeholder的解析都由它来完成: 分析PropertySourcesPlaceholdersResolver发现,真正完成解析是由PropertyPlaceholderHelper完成,PropertySourcesPlaceholdersResolver 在构造的时候就会创建一个PropertyPlaceholderHelper PropertySourcesPlaceholdersResolver 在创建 PropertyPlaceholderHelper 的时候会传递三个参数:前缀、后缀、默认值分割符,分别由以下三个常量表示: 这样 PropertyPlaceholderHelper 在解析placeholder时就能知道以什么格式来解析比如:${spring.application.name}这个placeholder就会被解析成属性值。 SpringBoot的配置非常灵活配置可以来自文件、环境变量、JVM系统属性、配置中心等等,SpringBoot通过 PropertySource和PropertySources实现属性优先级、CRUD的统一管理,为开发者提供统一的配置抽象。 -END- SpringBoot是如何加载配置文件的? 标签:tcl 环境 alt meta 一个 com || contain add 原文地址:https://blog.51cto.com/15054050/2563392
带着我们的问题一起去看一下SpringBoot配置相关的源代码,找出问题的答案。SpringBoot从哪里开始加载配置文件?
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
...
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
...
}
# Application Listeners
org.springframework.context.ApplicationListener= org.springframework.boot.context.config.ConfigFileApplicationListener
...
class SpringApplicationRunListeners {
private final Log log;
private final List
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class>[] types = new Class>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener
小结
SpringBoot从哪些地方加载配置文件?
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
private static final String DEFAULT_NAMES = "application";
上面说的是没有额外配置的情况,SpringBoot足够灵活可以指定配置文件搜索路径、配置文件名,在ConfigFileApplicationListener类中有个getSearchLocations方法,它主要负责获取配置搜索目录:private Set
这里就可以确定SpringBoot配置的搜索路径有两种情况:如果配置了spring.config.location则直接使用,否则使用spring.config.additional-location的属性值 + 默认搜索路径。SpringBoot是如何支持yaml和properties类型的配置文件?
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
...
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
getClass().getClassLoader());
}
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=org.springframework.boot.env.PropertiesPropertySourceLoader,org.springframework.boot.env.YamlPropertySourceLoader
看名字就知道是分别负责properties和yaml的啦。如果要支持json配置应该如何做?
public class JSONPropertySourceLoader implements PropertySourceLoader {
@Override
public String[] getFileExtensions() {
return new String[] {"json"};
}
@Override
public List
org.springframework.boot.env.PropertySourceLoader=com.csbaic.arch.spring.env.loader.JSONPropertySourceLoader
{
"spring.application.name": "JSONConfig"
}
2019-11-02 14:50:17.730 INFO 55275 --- [ main] c.c.a.spring.env.SpringEnvApplication : JSONConfig
SpringBoot的配置优化级是怎么样的?
另外为了集中管理PropertySource还抽象出一个PropertySources接口,PropertySources就一个实现类叫:MutablePropertySources,它将所有的PropertySource都放置在一个名叫propertySourceList集合中,同时提供一些修改操作方法:public void addFirst(PropertySource> propertySource) {}
public void addLast(PropertySource> propertySource) {}
public void addBefore(String relativePropertySourceName, PropertySource> propertySource) {}
public void addAfter(String relativePropertySourceName, PropertySource> propertySource) {}
public int precedenceOf(PropertySource> propertySource) { }
public PropertySource> remove(String name) {}
public void replace(String name, PropertySource> propertySource) {}
placeholder是如何被解析的?
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(this.environment);
}
public PropertySourcesPlaceholdersResolver(Iterable
public static final String PLACEHOLDER_PREFIX = "${";
public static final String PLACEHOLDER_SUFFIX = "}";
public static final String VALUE_SEPARATOR = ":";
总结
架构文摘
ArchDigest
架构知识丨大型网站丨大数据丨机器学习
如有收获,点个在看,诚挚感谢图片
文章标题:SpringBoot是如何加载配置文件的?
文章链接:http://soscw.com/index.php/essay/63192.html