我们正在创建一个使用数据库作为存储库的新 PropertySource
。这个想法是我们可以在运行时更新属性值。
同时,我们希望使用 @ConfigurationProperties
来包含验证以及使用 application-{profile} 命名约定。
但是,@ConfigurationProperties
的值似乎仅从“applicationConfig: [path/to/config]”PropertySource
加载。例如下面的测试:
private final String OVERRIDEN_VALUE = "overriden value";
@Before
public void before() {
LOGGER.debug("Property sources are: ");
for(Iterator<?> it = env.getPropertySources().iterator(); it.hasNext(); ) {
PropertySource<?> propertySource = (PropertySource<?>) it.next();
LOGGER.debug(propertySource.getName());
}
EnvironmentTestUtils.addEnvironment("integrationTest", env, "some.prefix.overridable-property=" + OVERRIDEN_VALUE);
}
@Test
public void testOverridingDefaultProperties() {
LOGGER.debug("MutablePropertySources value: {}", env.getProperty("some.prefix.overridable-property"));
LOGGER.debug("@ConfigurationProperties value: {}", testProperties.getOverridableProperty());
Assert.assertEquals(OVERRIDEN_VALUE, testProperties.getOverridableProperty());
}
产生这个输出:
Property sources are:
systemProperties
systemEnvironment
random
integrationTest
applicationConfig: [classpath:/path/to/my/application.yml]
MutablePropertySources value: overriden value
@ConfigurationProperties value: default value
有关更多上下文,我最初在 Spring Boot 的 Github 上问过这个问题 here .
最佳答案
感谢 Spring Boot 人员。向我指出 Spring Cloud Context
http://projects.spring.io/spring-cloud/spring-cloud.html#customizing-bootstrap-property-sources
看起来这样就可以了。
更新:
因为我们已经编写了额外的数据库支持的PropertySource
,所以我们实际上只需要在运行时刷新@ConfigurationProperties
。同时我们不想刷新所有的@ConfigurationProperties
。为完成刷新,我们执行了以下操作:
- 创建了一个名为
@ReloadableProperties
的注释 - 创建了以下使用 Spring Boot 的
ConfigurationPropertiesBindingPostProcessor
的实用程序 bean
/** * * Helper bean to reload {@code @ConfigurationProperties} * if the {@code @ConfigurationProperties} bean is annotated * with {@code @ReloadableProperties}. * * @author Jonathan Martin * @since 2.0.0 * * @see ReloadableProperties * @see ConfigurationPropertiesBindingPostProcessor * */ public class ConfigurationPropertiesReloader { private final ApplicationContext context; private final ConfigurationPropertiesBindingPostProcessor processor; @Autowired public ConfigurationPropertiesReloader(ApplicationContext context, ConfigurationPropertiesBindingPostProcessor processor) { this.context = context; this.processor = processor; } /** * Reload all {@code @ConfigurationProperties} * annotated with {@code @ReloadableProperties}. */ public void reload() { Map beans = context.getBeansWithAnnotation(ReloadableProperties.class); for (Map.Entry entry : beans.entrySet()) { String beanName = entry.getKey(); Object bean = entry.getValue(); ConfigurationProperties annotation = AnnotationUtils.findAnnotation(bean.getClass(), ConfigurationProperties.class); // Only reload the bean if it's an @ConfigurationProperties // Can't check for instance of ConfigurationPropertiesHolder // because it uses package scope. if (annotation != null) { processor.postProcessBeforeInitialization(bean, beanName); } } } }
现在,如果我将实用程序 bean 注入(inject)到我的测试中并调用重新加载,测试就会通过。
关于java - 如何构建自定义 PropertySource 以绑定(bind)到 @ConfigurationProperties,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31456216/