我们正在创建一个使用数据库作为存储库的新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上提出了这个问题。
答案 0 :(得分:2)
感谢Spring Boot的人们。向我指出Spring Cloud Context
http://projects.spring.io/spring-cloud/spring-cloud.html#customizing-bootstrap-property-sources
看起来这样可以解决问题。
<强>更新强>
由于我们已经编写了额外的数据库支持的numeric_limits
,我们实际上只需要在运行时刷新PropertySource
。与此同时,我们并不想刷新所有@ConfigurationProperties
。为了完成刷新,我们做了以下事情:
@ConfigurationProperties
@ReloadableProperties
/** * * 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注入我的测试并调用reload,则测试通过。