hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

SpringBoot是怎样加载配置文件的?

2019-11-18杂谈搜奇网38°c
A+ A-

媒介

本文针对版本2.2.0.RELEASE来剖析SpringBoot的设置处置惩罚源码,经由过程检察SpringBoot的源码来弄清楚一些罕见的题目比方:

  1. SpringBoot从那里最先加载设置文件?
  2. SpringBoot从哪些处所加载设置文件?
  3. SpringBoot是怎样支撑yamlproperties范例的设置文件?
  4. 假如要支撑json设置应当怎样做?
  5. SpringBoot的设置优先级是怎样的?
  6. placeholder是怎样被剖析的?

带着我们的题目一同去看一下SpringBoot设置相干的源代码,找出题目的答案。

SpringBoot从那里最先加载设置文件?

SpringBoot加载设置文件的进口是由ApplicationEnvironmentPreparedEvent事宜进入的,SpringBoot会在SpringApplication的组织函数中经由过程spring.factories文件猎取ApplicationListener的实例类:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    ...
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    ...
}

spring.factories中有一个ConfigFileApplicationListener类,它会监听ApplicationEnvironmentPreparedEvent然后再加载设置文件 :

# Application Listeners
org.springframework.context.ApplicationListener= org.springframework.boot.context.config.ConfigFileApplicationListener
...

有了事宜和事宜处置惩罚的类后,再找出发送事宜的处所,就可以够搞清楚SpringBoot是怎样加载设置文件的了,SpringBoot在启动之前先初始化好SpringApplicationRunListeners这个类,它会完成SpringApplicationRunListener接口然后对事宜举行转发:

class SpringApplicationRunListeners {

    private final Log log;

    private final List<SpringApplicationRunListener> listeners;

    SpringApplicationRunListeners(Log log, Collection<? extends SpringApplicationRunListener> listeners) {
        this.log = log;
        this.listeners = new ArrayList<>(listeners);
    }
 
    void environmentPrepared(ConfigurableEnvironment environment) {
        for (SpringApplicationRunListener listener : this.listeners) {
            listener.environmentPrepared(environment);
        }
    }
    ...
}

猎取SpringApplicationRunListeners的代码以下:


private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
    return new SpringApplicationRunListeners(logger,
            getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

一样也会去加载spring.factories文件,该文件有一个EventPublishingRunListener类,该类的作用就是SpringBoot的事宜转换成ApplicationEvent发送出去。

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

小结

  • SpringBoot会将事宜转换成ApplicationEvent再分发
  • SpringBoot是经由过程监听ApplicationEnvironmentPreparedEvent事宜来加载设置文件的
  • ConfigFileApplicationListener是处置惩罚设置文件的重要类

SpringBoot从哪些处所加载设置文件?

上面已剖析到ConfigFileApplicationListener是处置惩罚设置文件的重要类,然后进一步的检察SpringBoot是从哪些地点加载设置文件,进入ConfigFileApplicationListener类后会有两个默许的常量:

private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
private static final String DEFAULT_NAMES = "application";

首先在没有任何设置的状况下,会从DEFAULT_SEARCH_LOCATIONS常量列出来的位置中加载文件名为DEFAULT_NAMES(.properties或yml)的文件,默许位置包含:

  • classpath根目次(classpath:/)
  • classpath内里的config文件目次(classpath:/config/)
  • 顺序运转目次(file:./)
  • 顺序运转目次下的config目次(file:./config/)

上面说的是没有分外设置的状况,SpringBoot充足天真能够指定设置文件搜刮途径、设置文件名,在ConfigFileApplicationListener类中有个getSearchLocations要领,它重要担任猎取设置搜刮目次:

private Set<String> getSearchLocations() {
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
        return getSearchLocations(CONFIG_LOCATION_PROPERTY);
    }
    Set<String> locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
    locations.addAll(
            asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
    return locations;
}

它的操纵步骤大抵以下:

  1. 搜检是不是有spring.config.location属性,假如存在则直接运用它的值
  2. spring.config.additional-location属性中猎取搜刮途径
  3. 将默许搜刮途径添加到搜刮鸠合

这里就可以够肯定SpringBoot设置的搜刮途径有两种状况:假如设置了spring.config.location则直接运用,不然运用spring.config.additional-location的属性值 + 默许搜刮途径。

SpringBoot是怎样支撑yamlproperties范例的设置文件?

SpringBoot的设置支撑propertiesyaml文件,SpringBoot是怎样剖析这两种文件的呢,继承剖析ConfigFileApplicationListener这个类,内里有个子类叫Loader加载设置文件重要的事情就是由这货担任,然则直接读取propertiesyaml并转换成PropertySource照样由内里的PropertySourceLoader担任:

Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
    ...
    this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
            getClass().getClassLoader());
}

组织Loader对象的时刻就会先加载PropertySourceLoader,加载体式格局照样从spring.factories中读取:

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

个中设置了两个PropertySourceLoader的完成类:

  • PropertiesPropertySourceLoader
  • YamlPropertySourceLoader

看名字就晓得是离别担任propertiesyaml的啦。

假如要支撑json设置应当怎样做?

假如不喜欢propertiesyaml这两种花样,想要定义json做为设置笔墨花样能够直接定义json范例的PropertySourceLoader:

public class JSONPropertySourceLoader implements PropertySourceLoader {

    @Override
    public String[] getFileExtensions() {
        return new String[] {"json"};
    }
    
    @Override
    public List<PropertySource<?>> load(String name, Resource resource) throws IOException {

        if(resource == null || !resource.exists()){
            return Collections.emptyList();
        }

        Map<String, Object> configs = JSON.parseObject(resource.getInputStream(), Map.class);

        return Collections.singletonList(
                new MapPropertySource(name, configs)
        );
    }
}

然后在resources目次内里竖立个META-INF,再添加个spring.factories内里的内容以下:

org.springframework.boot.env.PropertySourceLoader=\
com.csbaic.arch.spring.env.loader.JSONPropertySourceLoader

末了在resources目次内里建个application.json的设置文件 :

{
  "spring.application.name": "JSONConfig"
}

一般启动SpringBoot猎取spring.applicaiton.name的设置的值就是JSONConfig

2019-11-02 14:50:17.730  INFO 55275 --- [           main] c.c.a.spring.env.SpringEnvApplication    : JSONConfig

SpringBoot的设置优先级是怎样的?

SpringBoot中有个PropertySource接口,特地用来保留属性罕见的完成类有:

  • CommandLinePropertySource
  • MapPropertySource
  • SystemEnvironmentPropertySource
  • ....

别的为了集合治理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) {}

一切的PropertySource都保留在propertySourceList中,越小的索引优先级越高,所以假如想要掩盖属性只需保证优化级够高就行。

placeholder是怎样被剖析的?

继承剖析ConfigFileApplicationListenerLoader子类,在组织时还会建立一个PropertySourcesPlaceholdersResolver,placeholder的剖析都由它来完成:

Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {

    this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(this.environment);
}

剖析PropertySourcesPlaceholdersResolver发明,真正完成剖析是由PropertyPlaceholderHelper完成,PropertySourcesPlaceholdersResolver 在组织的时刻就会建立一个PropertyPlaceholderHelper

public PropertySourcesPlaceholdersResolver(Iterable<PropertySource<?>> sources, PropertyPlaceholderHelper helper) {
    this.sources = sources;
    this.helper = (helper != null) ? helper : new PropertyPlaceholderHelper(SystemPropertyUtils.PLACEHOLDER_PREFIX,
            SystemPropertyUtils.PLACEHOLDER_SUFFIX, SystemPropertyUtils.VALUE_SEPARATOR, true);
}

PropertySourcesPlaceholdersResolver 在建立 PropertyPlaceholderHelper 的时刻会通报三个参数:前缀、后缀、默许值支解符,离别由以下三个常量示意:

public static final String PLACEHOLDER_PREFIX = "${";
public static final String PLACEHOLDER_SUFFIX = "}";
public static final String VALUE_SEPARATOR = ":";

如许 PropertyPlaceholderHelper 在剖析placeholder时就可以晓得以什么花样来剖析比方:${spring.application.name}这个placeholder就会被剖析成属性值。

总结

SpringBoot的设置异常天真设置能够来自文件、环境变量、JVM体系属性、设置中间等等,SpringBoot经由过程
PropertySourcePropertySources完成属性优先级、CRUD的一致治理,为开发者供应一致的设置笼统。





《架构文摘》天天一篇架构范畴重磅好文,触及一线互联网公司运用架构(高可用、高性 能、高稳固)、大数据、机械进修等各个热点范畴。

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
SpringBoot是怎样加载配置文件的?

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282278.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>