简体   繁体   English

在Spring Boot应用程序中添加条件外部PropertySource

[英]Adding a conditional external PropertySource in a spring boot application

I'm currently using an EnvironmentPostProcessor to add my external PropertySource, the code looks like this : 我当前正在使用EnvironmentPostProcessor添加我的外部PropertySource,代码如下所示:

public class ExternalPropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor
{
    private static final String EXTERNAL_PROPERTY_SOURCE_NAME = "ExternalPropertySource";

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application)
    {
        if (environment.acceptsProfiles(Profiles.EXTERNAL_PROPERTY_SOURCE_ENABLED_PROFILE)) {
            environment.getPropertySources()
                       .addLast(new ExternalPropertySource(EXTERNAL_PROPERTY_SOURCE_NAME, new ExternalSource()));
        }
    }
}

A spring.factories is also used to register this EnvironmentPostProcessor. spring.factories也用于注册此EnvironmentPostProcessor。

This code actually works if the profile is set in the vm environment variables, but if it is added in src/main/resources/application.yml, the profile doesn't seem to be injected yet in the environment and is not returned by the environment.getActiveProfiles(). 如果在vm环境变量中设置了配置文件,则此代码实际上有效,但是如果将其添加到src / main / resources / application.yml中,则该配置文件似乎尚未注入环境中,并且不会由配置文件返回。 environment.getActiveProfiles()。 I've tried using the interface Ordered with the lowest precedence, but it doesn't help. 我尝试使用优先级最低的接口Ordered,但这无济于事。

To add a bit of context around what I'm trying to achieve, this class is in a small library that adds an external property source like a database. 为了在我要实现的目标周围添加一些上下文,该类在一个小的库中,该库添加了外部属性源(如数据库)。 Then we can use it in some other spring boot applications. 然后,我们可以在其他一些Spring Boot应用程序中使用它。 Something like Spring Cloud Config does. 像Spring Cloud Config一样。

I'd like a clean way to enable or disable this property source depending on the environment where the code runs. 我想要一种干净的方法来启用或禁用此属性源,具体取决于代码运行的环境。 I don't mind using something else then profiles or even another way to inject the property source, I just want something clean that doesn't depend on several factors to work. 我不介意使用其他任何东西,然后再使用概要文件,甚至不使用其他方式注入属性源,我只想要一些不依赖于几个因素才能工作的干净东西。

The main problem in my code right now is that I'm using spring boot's property sources to make my own property source configurable. 现在,我的代码中的主要问题是我正在使用Spring Boot的属性源来使自己的属性源可配置。

UPDATE : I used a Spring Cloud app to debug this, and was confusing the bootstrap context with the normal spring boot context. 更新:我使用Spring Cloud应用程序进行调试,并且将引导上下文与普通的Spring Boot上下文混淆了。 See my answer below. 请参阅下面的答案。

Further investigation made me figure out the problem appeared only with a Spring Cloud application. 进一步的调查使我发现问题仅出现在Spring Cloud应用程序中。

In fact the breakpoint I had in this code was triggered twice, once after the bootstrap context initialization and once after the spring boot context initialization. 实际上,我在这段代码中的断点被触发了两次,一次是在引导上下文初始化之后,一次是在spring boot上下文初始化之后。 I was only debugging the profiles in the first occurence. 我只是在第一次出现时调试配置文件。 At that point, only the bootstrap.yml properties are loaded and not the ones from the application.yml file. 那时,仅加载bootstrap.yml属性,而不加载application.yml文件中的属性。 The second occurence obviously had the profiles from my application.yml file. 显然第二次出现具有我的application.yml文件中的配置文件。

My code worked as expected with a vanilla Spring Boot application. 我的代码在香草Spring Boot应用程序中按预期工作。 As the documentation states : 文档所述:

The Environment has already been prepared with all the usual property sources that Spring Boot loads by default. 环境已经准备好了Spring Boot默认加载的所有常用属性源。

I was confused by the behaviour of my app which seemed to be different from that statement, but it was Spring Cloud's bootstrap that was messing with my debugging. 我的应用程序的行为似乎与该声明不同,这让我感到困惑,但是正是Spring Cloud的引导程序使我的调试陷入困境。

Since I need a PropertySource that has the highest precedence, I need to add it in the post bootstrap initialization for Spring Cloud apps. 由于我需要具有最高优先级的PropertySource,因此需要将其添加到Spring Cloud应用程序的启动后初始化中。 I used an init flag on my EnvironmentPostProcessor so it doesn't get executed twice and used the bootstrap.yml on Spring Cloud apps to set the profile. 我在EnvironmentPostProcessor上使用了一个初始化标志,因此它不会执行两次,并在Spring Cloud应用程序中使用了bootstrap.yml来设置配置文件。

TL;DR : With Spring Cloud, an EnvironmentPostProcessor gets called twice: once after the bootstrap init and once after the normal Spring Boot context init. TL; DR:使用Spring Cloud,两次调用EnvironmentPostProcessor:一次在引导初始化之后,一次在常规Spring Boot上下文初始化之后。 If you need injected properties and are targeting the Spring Cloud's post bootstrap initialization, use the bootstrap.yml instead of application.yml. 如果您需要注入的属性并且针对Spring Cloud的引导后初始化,请使用bootstrap.yml而不是application.yml。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM