在 spring 引导应用程序中添加条件外部 PropertySource

Adding a conditional external PropertySource in a spring boot application

我目前正在使用 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()));
        }
    }
}

一个spring.factories也用来注册这个EnvironmentPostProcessor。

如果在 vm 环境变量中设置配置文件,此代码实际上有效,但如果将其添加到 src/main/resources/application.yml 中,配置文件似乎尚未注入环境中,并且不是由 environment.getActiveProfiles() 返回。我试过使用优先级最低的 Ordered 接口,但没有用。

为了围绕我要实现的目标添加一些上下文,这个 class 在一个小型库中,它添加了一个外部 属性 源,如数据库。然后我们可以在其他一些 spring 启动应用程序中使用它。 Spring Cloud Config 之类的东西。

我想要一种干净的方式来启用或禁用此 属性 源,具体取决于代码运行的环境。我不介意使用其他东西然后配置文件或什至另一种方式来注入 属性 源,我只想要一些干净的东西,不依赖于几个因素来工作。

我现在代码中的主要问题是我正在使用 spring boot's property sources 使我自己的 属性 源可配置。

更新:我使用 Spring 云应用程序对此进行调试,并且混淆了 bootstrap 上下文与正常的 spring 启动上下文。请参阅下面我的回答。

进一步调查让我发现问题只出现在 Spring 云应用程序中。

事实上,我在这段代码中设置的断点被触发了两次,一次是在 bootstrap 上下文初始化之后,一次是在 spring 引导上下文初始化之后。我只是在调试第一次出现的配置文件。此时,仅加载 bootstrap.yml 属性,而不加载 application.yml 文件中的属性。第二次出现显然是我的 application.yml 文件中的配置文件。

我的代码在 vanilla Spring Boot 应用程序中按预期工作。正如 documentation 所述:

The Environment has already been prepared with all the usual property sources that Spring Boot loads by default.

我对我的应用程序的行为感到困惑,它似乎与该声明不同,但正是 Spring Cloud 的 bootstrap 扰乱了我的调试。

由于我需要一个具有最高优先级的 PropertySource,因此我需要将其添加到 post bootstrap 初始化 Spring 云应用程序中。我在我的 EnvironmentPostProcessor 上使用了一个初始化标志,所以它不会被执行两次,并在 Spring 云应用程序上使用 bootstrap.yml 来设置配置文件。

长话短说: 使用 Spring Cloud,EnvironmentPostProcessor 被调用两次:一次在 bootstrap init 之后,一次在正常的 Spring Boot context init 之后。如果您需要注入的属性并且目标是 Spring Cloud 的 post bootstrap 初始化,请使用 bootstrap.yml 而不是 application.yml.