我正在构建一个库,该库为使用我们Spring Cloud Config/Eureka
设置的应用程序提供了一个固定的配置。我们的想法是将此配置作为自定义启动器提供,在单个微服务应用程序中很少或不使用与弹簧云相关的样板。
此时,我想要放在此库中的大部分共享配置都包含bootstrap.yml
中的内容。我想在我的自定义启动器中提供bootstrap.yml
,但使用该库的应用程序仍然需要能够提供自己的bootstrap.yml
,即使这样他们也可以设置他们的spring.application。说得好。
由于从类路径加载bootstrap.yml
的方式,如果应用程序有自己的bootstrap.yml
,Spring似乎忽略了共享库中的那个。由于引导上下文处理ApplicationContextInitializer
的特殊方式,我甚至无法使用ApplicationContextInitializers
来自定义环境。
有没有人对此方法有效?我想提供一个drop-in lib,它使我们自以为是的bootstrap配置工作,而不必在所有项目中复制样板bootstrap.yml
。
答案 0 :(得分:3)
您可以使用org.springframework.cloud.bootstrap.BootstrapConfiguration
文件中的META-INF/spring.factories
键将共享库中的PropertySource添加到引导程序属性中。
例如,您可以创建包含以下内容的库:
<强>的src /主/ JAVA / COM /示例/ MYLIB / MyLibConfig.java 强>
package com.example.mylib;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:mylib-config.properties")
public class MyLibConfig {
}
<强>的src /主/资源/ mylib-config.properties 强>
eureka.instance.public=true
# or whatever...
<强>的src /主/资源/ META-INF / spring.factories 强>
org.springframework.cloud.bootstrap.BootstrapConfiguration=com.example.mylib.MyLibConfig
更多详情:http://projects.spring.io/spring-cloud/spring-cloud.html#_customizing_the_bootstrap_configuration
答案 1 :(得分:1)
我能够找到解决方案。该解决方案的目标是:
主要挑战是在应用程序生命周期的适当位置注入一些代码。具体来说,我们需要在将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
有几点需要注意:
编辑:我的初步答案无效。我用这个代替了它。