重寫spring cloud config 本地bootstrap

在spring-cloud中使用了config-server以後,須要在client端加入bootstrap做爲配置文件,其中一般包含以下:
spring.application.name=ms-asset
spring.cloud.config.label=master
spring.cloud.config.profile=test
spring.cloud.config.uri=http://ms-config-server-srv:8001/
可是這樣的配置存在問題,因其固定了使用的配置環境和label,如採用Docker部署,則沒法經過環境變量更改,經過閱讀源碼可知,Spring-cloud 經過兩個JVM參數控制加載的配置文件。
-Dspring.cloud.config.label=master
-Dspring.cloud.config.profile=test
其中label表示分支,profile表示加載的配置環境。
其源碼很是簡單,在ConfigClientProperties中,以下所示:
public ConfigClientProperties override(
            org.springframework.core.env.Environment environment) {
        ConfigClientProperties override = new ConfigClientProperties();
        BeanUtils.copyProperties(this, override);
        override.setName(
                environment.resolvePlaceholders("${" + ConfigClientProperties.PREFIX
                        + ".name:${spring.application.name:application}}"));
        if (environment.containsProperty(ConfigClientProperties.PREFIX + ".profile")) {
            override.setProfile(
                    environment.getProperty(ConfigClientProperties.PREFIX + ".profile"));
        }
        if (environment.containsProperty(ConfigClientProperties.PREFIX + ".label")) {
            override.setLabel(
                    environment.getProperty(ConfigClientProperties.PREFIX + ".label"));
        }
        return override;
    }
能夠看出,spring cloud僅支持profile和label這兩個配置注入,在通常狀況下足夠用了。
另外存在一種修改spring-boot配置文件的方式,原理是監測spring初始化完成的事件,而後將環境變量注入配置中,可用於覆蓋spring cloud config server的統一配置,但因爲bootstrap處在加載鏈的最前端,在初始化以前即以完成的遠程配置文件的加載,所以該方法無效,一併貼出,有緣人自取。
package com.example;

import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ConfigServicePropertyDeprioritizer
        implements ApplicationListener<ApplicationPreparedEvent>
{
    private static final String CONFIG_SOURCE = "bootstrap";

    private static final String PRIORITY_SOURCE = "systemEnvironment";

    @Override
    public void onApplicationEvent(ApplicationPreparedEvent event)
    {
        ConfigurableEnvironment environment = event.getApplicationContext()
                .getEnvironment();
        MutablePropertySources sources = environment.getPropertySources();
        PropertySource<?> bootstrap = findSourceToMove(sources);

        if (bootstrap != null)
        {
            sources.addAfter(PRIORITY_SOURCE, bootstrap);
        }
    }

    private PropertySource<?> findSourceToMove(MutablePropertySources sources)
    {
        boolean foundPrioritySource = false;

        for (PropertySource<?> source : sources)
        {
            if (PRIORITY_SOURCE.equals(source.getName()))
            {
                foundPrioritySource = true;
                continue;
            }

            if (CONFIG_SOURCE.equals(source.getName()))
            {
                // during bootstrapping, the "bootstrap" PropertySource
                // is a simple MapPropertySource, which we don't want to
                // use, as it's eventually removed. The real values will 
                // be in a CompositePropertySource
                if (source instanceof CompositePropertySource)
                {
                    return foundPrioritySource ? null : source;
                }
            }
        }

        return null;
    }
}
相關文章
相關標籤/搜索