首页 > 解决方案 > Spring Boot 中动态属性的选项

问题描述

我有一个应用程序以属性的形式进行了一些外部化配置。我希望应用程序能够对此类属性的更改做出反应,而无需重新启动或完全刷新上下文。

我不清楚我的选择是什么。

人工示例:应用程序实现了一个服务,该服务接收请求并决定是排队还是拒绝它们。队列的最大大小是一个属性。

final int queueMaxSize = queueProperties.getMaxSize();
if (queue.size() >= queueMaxSize) { //reject }

QueueProperties用@ConfigurationProperties 注释的类在哪里。

@ConfigurationProperties(prefix = "myapp.limits.queue")
@Getter
@Setter
public class QueueProperties {
  public int maxSize = 10;
}

这可以让我通过系统属性、配置文件等来控制行为。 但是,我希望能够在不释放/部署/重新启动/刷新应用程序的情况下更改此值。

我的应用程序已经使用Archaius。如果我使用我们的内部基础设施为这个属性推送一个新值,我可以看到应用程序 Spring Environment 确实收到了新值。(例如,/admin/env反映价值并动态变化)。

我不清楚的部分是:如何让我的服务对环境中的价值变化做出反应?

我找到了两种方法,但它们看起来很毛茸茸,我想知道是否有更好的选择。我预计这将成为 Spring 生态系统中一流解决方案的常见问题。

哈克解决方案#1:

@Bean
@Scope("prototype")
@ConfigurationProperties(prefix = "myapp.limits.queue")
QueueProperties queueProperties() {
    return new QueueProperties();
}

并使用 as 属性将其注入服务Provider<QueueProperties>并将其用作queuePropertiesProvider.get().getMaxSize().

这可行,但有一些我不喜欢的副作用:

哈克解决方案#2:

不要用 注释我的属性类ConfigurationProperties,在构建时注入 Spring 环境。像这样实现getter:

int getMaxSize() {
   return environment.getProperty("myapp.limits.queue", 10);
}

这在行为方面也可以。但是 - 这没有被注释为属性(与这个大型项目中的其他属性类不同,这使得它更难找到) - 这个类没有出现在/admin/configprops

哈克解决方案#3:

安排Environment用于更新我的单例QueuePropertiesbean 的重复任务。

任何进一步的想法/建议/指针?是否有一种规范/推荐的方法可以做到这一点,并且没有上述解决方案的缺点?

标签: javaspringspring-bootconfiguration

解决方案


推荐阅读