Событие Spring Cloud Refresh не распознает удаленные свойства?

Предыстория:

У меня есть приложение Spring Boot 1.4, работающее с Spring Cloud. Мое приложение использует собственный профиль для получения настроек из внешнего файла config.properties. Сервер конфигурации встроен в то же приложение.

В файле config.properties я добавил следующий параметр:

app.setting=helloworld

Что работает:

Когда я изменяю свойство и отправляю событие REFRESH, соответствующие отмеченные bean-компоненты перезагружаются, и изменение распознается правильно.

Что не работает:

Если я фактически удалю свойство из config.properties (например, закомментировав его), событие REFRESH не сделает ничего для фактического обновления приложения. Spring Cloud, кажется, не распознает тот факт, что свойство удалено, и когда связыватель данных продолжает обновлять состояние мира, он пропускает тот факт, что свойство удалено, и соответствующий компонент, связанный с ним, также должен быть обновлен, и его поле установлено пустым/нулевым и т. д.

Похоже, что сборщик данных смотрит только на то, что в данный момент доступно в конфигурации, и не ведет учет что было по сравнению с тем, что есть.

Единственный способ фактически отключить этот параметр в состоянии конфигурации bean-компонента — не удалить его, а фактически установить для него пустое значение (которое является новым значением, учитывая, что параметр является просто строкой). Обратите внимание, что поле в Java-бине, сопоставленное с этим свойством, не имеет значения по умолчанию, отличного от null, и это значение не определено нигде (например, во встроенном файле application.properties и т. д.).

  1. Что я могу упустить?
  2. Это особенность? Ошибка?

Спасибо за ваше время.


person Misagh Moayyed    schedule 13.08.2016    source источник


Ответы (2)


Я столкнулся с подобной проблемой при обновлении внешнего файла config.properties. Проблема проявилась с моим config.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». Он не распознал, что поле было удалено, и не использовал значение «abc» из application.properties.

Проблема связана с классом ConfigFileApplicationListener, который в строке 428 идентифицирует файл свойств как пустой, поэтому не загружает файл в источники свойств, которые позже используются для сравнения новых свойств с старый в ContextRefresher. Сценарий, кажется, сохраняет в памяти старый.

Чтобы обойти эту проблему, когда у вас есть только одно свойство, вы можете добавить свойство, такое как a.b, которое заставит файл загружаться без значения и приведет к правильной функциональности.

config.properties

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

Надеюсь это поможет

person Robin    schedule 06.03.2017

Не уверен, что это применимо к вам, но у меня была аналогичная проблема с bean-компонентами, аннотированными с помощью @ConfigurationProperties и зарегистрированными с использованием @EnableAutoConfiguration:

@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 не позволяет изменить область действия компонента, а это означает, что компонент не создается повторно при обновлении контекста. См. раздел ошибка Github.

Мое исправление

Я удалил MyConfig из @EnableAutoConfiguration и явно добавил аннотацию @Component:

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

@EnableAutoConfiguration
public class ApplicationConfiguration {
}

После этого удаление элементов из списка YAML отражается в MyConfig при обновлении контекста.

person lmika    schedule 12.01.2017