Spring Cloud Refresh事件无法识别已删除的属性?

时间:2016-08-13 11:21:27

标签: spring-boot spring-cloud spring-cloud-config

背景

我有一个运行Spring Cloud的Spring Boot 1.4应用程序。我的应用程序使用本机配置文件从外部config.properties文件中提取设置。配置服务器嵌入在同一个应用程序中。

在config.properties文件中,我添加了以下设置:

app.setting=helloworld

什么有效:

当我更改属性并发送REFRESH事件时,会重新加载标记的相关bean并正确识别更改。

什么行不通:

如果我实际上从config.properties中删除了该属性(例如通过注释掉它),则REFRESH事件不会实际刷新应用程序。 Spring Cloud似乎无法识别属性被删除的事实,当数据绑定器继续更新世界状态时,它错过了删除属性的事实,并且还必须刷新链接到它的相应bean,并且字段设置为空白/ null等。

看起来数据绑定器只查看配置中当前可用的内容,并且不记录什么是

在bean配置状态下实际禁用该设置的唯一方法不是删除它,而是通过实际将其设置为空值(这是一个新值,假设设置只是一个字符串)。请注意,映射到此属性的Java bean中的字段没有除null之外的默认值,并且该值未在其他任何位置定义(如在嵌入式application.properties文件中等)

  1. 我可能会失踪什么?
  2. 这是一个功能吗?错误?
  3. 感谢您的时间。

2 个答案:

答案 0 :(得分:2)

刷新外部config.properties文件时遇到了类似的问题。这个问题与我的config.properties有关,因为它只有一个单个条目。

演示:

首先覆盖应用程序属性

application.properties

some.value=abc

config.properties

some.value=xyz

最初,使用some.value将呈现“xyz”

要显示可以更新的值,请更改config.properties

中的值

config.properties

some.value=123

使用/ refresh端点刷新上下文然后使用some.value将呈现“123”

现在,通过删除属性,我们可以看到值没有得到更新

config.properties

// now empty

使用/ refresh端点刷新上下文,然后使用some.value 仍然渲染“123”。它没有认识到该字段已被删除,也未使用application.properties中的“abc”值。

问题源于第428行的类ConfigFileApplicationListener,它将属性文件标识为空,因此不会将文件加载到以后用于将新属性与旧属性进行比较的属性源中。 ContextRefresher课程。{{3}}。该场景似乎将旧的内容保留在内存中。

要解决此问题,当您只有一个属性时,可以添加类似a.b的属性,这将强制文件加载no值并产生正确的功能。

config.properties

a.b=true
// item removed, but use some property to make sure it's read later

希望这有帮助

答案 1 :(得分:1)

不确定这是否适用于您,但我在使用@ConfigurationProperties注释并使用@EnableAutoConfiguration注册的bean时遇到类似问题:

@ConfigurationProperties(prefix="example")
@RefreshScope
public class MyConfig {
    private List<String> values;
}

@EnableAutoConfiguration(MyConfig.class)
public class ApplicationConfiguration {
}

我遇到的问题是你有一个YAML配置,如:

example:
  - Some
  - Values
  - Here
在刷新上下文时,

从列表中删除项目并未将其从MyConfig.values中删除。

原因是使用MyConfig注册@EnableAutoConfiguration不允许您更改bean的范围,这意味着在刷新上下文时不会重新创建bean。请参阅Github Issue

我的修复

我从MyConfig删除了@EnableAutoConfiguration并明确添加了@Component注释:

@Component
@ConfigurationProperties(prefix="example")
@RefreshScope
public class MyConfig {
    private List<String> values;
}

@EnableAutoConfiguration
public class ApplicationConfiguration {
}

在此之后,当刷新上下文时,从YAML列表中删除项目会反映在MyConfig中。