Spring Boot:尝试使用EnvironmentPostProcessor覆盖application.properties

因此,我尝试使用存储在cosul中的键/值覆盖application.properties中的值。我尝试了两件事。

1)使用Spring Cloud Consul Config。 https://cloud.spring.io/spring-cloud-consul/reference/html/#spring-cloud-consul-config

如果我在application.properties中没有定义相同的键,则此方法有效。如果在application.properties中定义,则在所有@Value批注解析中使用属性文件中的值。这与我想要的相反。

2)由于上述操作无效,因此我继续创建了一个自定义的EnvironmentPostProcessor。我首先尝试构建一个MapPropertySource并使用environment.getPropertySources()。addAfter(..)。这与上面的结果相同。然后,我尝试遍历所有属性源,找到一个名称包含“ applicationconfig:[classpath:/ application”的名称,然后设置属性值(如果存在)或放置新的属性值。另外,我将MapPropertySource添加到了“ applicationconfig:[classpath:/ application“”属性源所在的EnumerableCompositePropertySource中。

无论采用哪种方法,结果始终相同。如果键存在于application.properties中,则使用该值。

有什么作用?我实际上是重写属性源中的值,并且在PostProcessor完成其工作之前,我可以在调试器中看到这些值。仍如何将application.properties值添加到@Value批注?

这是我当前的PostProcessor。

@Order(Ordered.LOWEST_PRECEDENCE)
public class ConsulPropertyPostProcessor implements EnvironmentPostProcessor {


    private static final String PROPERTY_SOURCE_NAME = "applicationconfigurationProperties";

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment,SpringApplication application) {
        PropertySource<?> system = environment.getPropertySources().get(SYSTEM_ENVironMENT_PROPERTY_SOURCE_NAME);

        ConsulKVService consulKVService = new ConsulKVServiceImpl().instantiateConsulKVServiceImpl((String)system.getProperty("CONSUL_HOST"),(String)system.getProperty("CONSUL_TOKEN"));
        Map<String,Object> map = consulKVService.getconsulKeysAndValuesByPrefix((String)system.getProperty("CONSUL_PREFIX"));


        addOrReplace(environment.getPropertySources(),map);
    }

    private void addOrReplace(MutablePropertySources propertySources,Map<String,Object> map) {
        MapPropertySource target = new MapPropertySource("applicationconfig: [consulKVs]",map);
        if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
            PropertySource<?> applicationconfigurationPropertySources = propertySources.get(PROPERTY_SOURCE_NAME);

            for(EnumerableCompositePropertySource applicationPropertySource : (ArrayList<EnumerableCompositePropertySource>)applicationconfigurationPropertySources.getsource()){
                if(applicationPropertySource.getName() != null
                        && applicationPropertySource.getName().contains("applicationconfig: [profile=")) {

                    for(PropertySource singleApplicationPropertySource : applicationPropertySource.getsource()){
                        if(singleApplicationPropertySource.getName().contains("applicationconfig: [classpath:/application")){

                            for (String key : map.keySet()) {
                                if(map.get(key) != null) {
                                    if (singleApplicationPropertySource.containsProperty(key)) {
                                        ((Properties) singleApplicationPropertySource.getsource())
                                                .setProperty(key,(String) map.get(key));
                                    } else {
                                        ((Properties) singleApplicationPropertySource.getsource()).put(key,(String) map.get(key));
                                    }
                                }
                            }
                            break;
                        }
                    }

                    applicationPropertySource.add(target);

                    break;


                }
            }

        }

    }
}

提前感谢大家。

编辑: 尝试覆盖ApplicationListener类的onApplicationEvent方法,其结果与上述相同。这是代码。

@Log4j
public class ConsulProperties implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {

    static ConfigurableEnvironment configurableEnvironment;
    private static final String PROPERTY_SOURCE_NAME = "applicationconfigurationProperties";

    public static ConfigurableEnvironment getconfigurableEnvironment() {
        return configurableEnvironment;
    }

    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        log.info("Received ApplicationEnvironmentPreparedEvent...");
        ConfigurableEnvironment environment = event.getEnvironment();
        configurableEnvironment = environment;
        Properties props = new Properties();

        ConsulKVService consulKVService = new ConsulKVServiceImpl()
                .instantiateConsulKVServiceImpl((String) configurableEnvironment.getProperty("CONSUL_HOST"),(String) configurableEnvironment.getProperty("CONSUL_TOKEN"));
        Map<String,Object> map = consulKVService.getconsulKeysAndValuesByPrefix((String) configurableEnvironment.getProperty("CONSUL_PREFIX"));
        while(map.values().remove(null));
        addOrReplace(environment.getPropertySources(),map);
    }


    private void addOrReplace(MutablePropertySources propertySources,map);
        if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
            PropertySource<?> applicationconfigurationPropertySources = propertySources.get(PROPERTY_SOURCE_NAME);

            for(EnumerableCompositePropertySource applicationPropertySource : (ArrayList<EnumerableCompositePropertySource>)applicationconfigurationPropertySources.getsource()){
                if(applicationPropertySource.getName() != null
                        && applicationPropertySource.getName().contains("applicationconfig: [profile=")) {

                    for(PropertySource singleApplicationPropertySource : applicationPropertySource.getsource()){
                        if(singleApplicationPropertySource.getName().contains("applicationconfig: [classpath:/application")){

                            for (String key : map.keySet()) {
                                if (singleApplicationPropertySource.containsProperty(key)) {
                                    ((Properties) singleApplicationPropertySource.getsource())
                                            .setProperty(key,(String) map.get(key));
                                } else {
                                    ((Properties) singleApplicationPropertySource.getsource()).put(key,map.get(key));
                                }
                            }


                            applicationPropertySource.add(target);

                            Properties properties = new Properties();
                            properties.putAll(map);
                            propertySources.addLast(new PropertiesPropertySource("consulKVs",properties));

                            break;
                        }
                    }


                    break;


                }
            }
        }
    }
}
zyai558 回答:Spring Boot:尝试使用EnvironmentPostProcessor覆盖application.properties

您似乎正在尝试更改spring并非为之设计的惯例。您提供的代码不太容易维护,并且需要对Spring内部结构有深入的了解。坦白说,我不能不调试就知道如何实现所需的内容,但是我想到了另一种方法:

您可以通过以下方式使用弹簧轮廓:

假设您在db.name=abc中拥有属性application.properties,在领事中拥有db.name=xyz,我假设您的目标是在春季之前解决db.name=xyz

在这种情况下,如果要从本地文件获取属性,请将db.name=abc移至application-local.properties并使用--spring.profiles.active=local启动应用程序,如果要从本地文件获取该属性,请使用领事。

您甚至可以在EnvironmentPostProcessor中动态添加活动配置文件(无论如何您已经在其中),但这是EnvironmentPostProcessor中的一行代码。

,

您的代码存在问题,您正在使用以下代码添加新的属性源。请注意,当您调用“ addLast”时,通过此方法添加的属性源的优先级最低,并且永远不会更新已经可用的属性。

propertySources.addLast(new PropertiesPropertySource("consulKVs",properties));

您可以使用“ addFirst”代替上面的代码添加属性源,该属性源应具有以下代码中给出的最高优先级。还有其他一些方法,例如“ addAfter”和“ addBefore”,您可以探索将属性源添加到准确的位置。无论如何,“ addFirst”在所有其他方式上都具有优先权,因此我认为您可以使用“ addFirst”来更新属性源。

propertySources.addFirst(new PropertiesPropertySource("consulKVs",properties));

我已经使用ApplicationEnvironmentPreparedEvent测试了此方案,并且工作正常。希望它能解决您的问题。

本文链接:https://www.f2er.com/3144112.html

大家都在问