如何管理共享库中的spring-cloud bootstrap属性?

我正在构建一个库,该库为使用我们的Spring Cloud

Config/Eureka设置的应用程序提供了合理的配置。这个想法是作为单个微服务应用程序中很少或没有与Spring云相关的样板的定制启动程序提供此配置的。

此时,我要放入此库中的大多数共享配置都包含中的内容bootstrap.yml。我想bootstrap.yml在我的自定义启动器中提供,但是使用该库的应用程序仍然需要能够提供自己的bootstrap.yml,即使这样也可以正确设置spring.application.name。

由于bootstrap.yml是从类路径加载的,因此,如果应用程序具有自己的,Spring似乎会忽略共享库中的那个bootstrap.ymlApplicationContextInitializer由于引导上下文对待的特殊方式,我什至无法使用自定义环境ApplicationContextInitializers

有人对在这里可行的方法有任何建议吗?我想提供一个嵌入式库,使我们自以为是的引导程序配置工作,而不必bootstrap.yml在所有项目中都复制样板。

回答:

我能够找到解决方案。该解决方案的目标是:

  • 从共享库中的yaml文件加载值。
  • 允许使用该库的应用程序引入自己的bootstrap.yml,并将它们也加载到环境中。
  • bootstrap.yml中的值应覆盖共享yaml中的值。

主要挑战是在应用程序生命周期的适当时间点注入一些代码。具体来说,我们需要在将bootstrap.yml

PropertySource添加到环境中之后执行此操作(以便我们可以按照相对于它的正确顺序注入自定义PropertySource),但也需要在应用程序开始配置Bean之前(作为配置值控件)行为)。

我发现的解决方案是使用自定义的EnvironmentPostProcessor

public class CloudyConfigEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {

private YamlPropertySourceLoader loader;

public CloudyConfigEnvironmentPostProcessor() {

loader = new YamlPropertySourceLoader();

}

@Override

public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication application) {

//ensure that the bootstrap file is only loaded in the bootstrap context

if (env.getPropertySources().contains("bootstrap")) {

//Each document in the multi-document yaml must be loaded separately.

//Start by loading the no-profile configs...

loadProfile("cloudy-bootstrap", env, null);

//Then loop through the active profiles and load them.

for (String profile: env.getActiveProfiles()) {

loadProfile("cloudy-bootstrap", env, profile);

}

}

}

private void loadProfile(String prefix, ConfigurableEnvironment env, String profile) {

try {

PropertySource<?> propertySource = loader.load(prefix + (profile != null ? "-" + profile: ""), new ClassPathResource(prefix + ".yml"), profile);

//propertySource will be null if the profile isn't represented in the yml, so skip it if this is the case.

if (propertySource != null) {

//add PropertySource after the "applicationConfigurationProperties" source to allow the default yml to override these.

env.getPropertySources().addAfter("applicationConfigurationProperties", propertySource);

}

} catch (IOException e) {

throw new RuntimeException(e);

}

}

@Override

public int getOrder() {

//must go after ConfigFileApplicationListener

return Ordered.HIGHEST_PRECEDENCE + 11;

}

}

可以通过META-INF / spring.factories注入此自定义的EnvironmentPostProcessor:

#Environment PostProcessors

org.springframework.boot.env.EnvironmentPostProcessor=\

com.mycompany.cloudy.bootstrap.autoconfig.CloudyConfigEnvironmentPostProcessor

需要注意的几件事:

  • YamlPropertySourceLoader按配置文件加载yaml属性,因此,如果您使用的是多文档yaml文件,则实际上需要分别从其中分别加载每个配置文件,包括无配置文件的配置。
  • ConfigFileApplicationListener是EnvironmentPostProcessor,负责将bootstrap.yml(或常规上下文中的application.yml)加载到环境中,因此,为了相对于bootstrap.yml属性正确地优先放置自定义yaml属性,您需要对命令进行排序ConfigFileApplicationListener之后的自定义EnvironmentPostProcessor。

以上是 如何管理共享库中的spring-cloud bootstrap属性? 的全部内容, 来源链接: utcz.com/qa/398383.html

回到顶部