java - 如何构建自定义 PropertySource 以绑定(bind)到 @ConfigurationProperties

标签 java spring-boot

我们正在创建一个使用数据库作为存储库的新 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。为完成刷新,我们执行了以下操作:

  1. 创建了一个名为 @ReloadableProperties 的注释
  2. 创建了以下使用 Spring Boot 的 ConfigurationPropertiesBindingPostProcessor
  3. 的实用程序 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/

相关文章:

java - REST资源异常拦截器

java - Swagger 中的重复条目

Javascript:是否可以将字符串转换为数组的数组?

docker-compose - 外部化 spring application.properties

java - 如何将 android keyEvent 的键码转换为 Robot 可以在台式机上使用的内容?

Java - 我不断丢失对全局类的引用

java - 使用套接字将 .jpg 从 Android 发送到 C++

java - 尝试在 Windows 10 计算机上运行时出现 Maven 错误

java - 使用 Eclipse 和 Maven 运行 SpringBoot JUnit-Tests 时的不同结果

Spring Data Rest - 如何在 @RepositoryEventHandler 中接收 header