繁体   English   中英

在 Spring 中存储和更改全局应用程序属性的最佳方法是什么 以线程安全的方式启动

[英]What is the best way to store and change global app properties in Spring Boot in a thread safe way

我正在使用 Spring 引导,并在我的应用程序启动时在 @Configuration bean 中加载/生成应用程序属性,并将它们放在 HashMap 中,例如:

@Configuration
public class Config {

  @Bean(name = "appConfig")
  public Map<String, String> getApplicationConfig() {

    Map<String, String> appConfig = new HashMap<>();

    //load or generate global config varibles
    appConfig.put("GLOBAL_CONFIG", "VALUE 1");
    return appConfig;
}

我在几个 bean 中注入了这个 map 属性,例如:

@RestController
@RequestMapping("/getglobalconfig")
public class ConfigController {

  @Value("#{appConfig}")
  private Map<String, String> appConfig;

  @GetMapping
  public String getGlobalConfig() { return appConfig.get("GLOBAL_CONFIG"); }
}

在某些事件之后,我想以线程安全的方式更改例如我的 appConfig HashMap GLOBAL_CONFIG 值的值,以便在所有注入的 bean 中更新它,例如上面的 ConfigController 示例。

以线程安全的方式完成此操作并让我的 bean 重新加载值而不重新初始化它们或重新启动应用程序的最佳模式是什么? Spring 云配置看起来很有趣,但不幸的是我无法使用它。

我不限于 HashMap 属性,我只需要线程安全地重新加载全局属性,以便在重新加载后在注入的 bean 中可见。

Spring 默认创建单例,因此所有 bean 将具有对属性 map 的相同引用。 但是,并发访问简单的 map 可能会产生错误。

因此,所需的最小更改是

 Map<String, String> appConfig = new java.util.concurrent.ConcurrentHashMap<>();

 //load or generate global config varibles
 appConfig.put("GLOBAL_CONFIG", "VALUE 1");
 return appConfig;

或者

 Map<String, String> appConfig = new HashMap<>();

 //load or generate global config varibles
 appConfig.put("GLOBAL_CONFIG", "VALUE 1");
  return java.util.Collections.synchronizedMap(appConfig);

但是,您使用的方法意味着其他 bean 也可以更改属性。 我会在 map 周围创建新的包装 bean,它只提供一种方法

public class ReadOnlyConfig {
  private  final Map map;
  public ReadOnlyConfig (Map map) { this.map = map; }
  String getProperty(String name) { return map.get(name); }
}

@Configuration
public class Config {

  @Bean(name = "appConfig")
  public Map<String, String> getApplicationConfig() {

    Map<String, String> appConfig = new java.util.concurrent.ConcurrentHashMap<>();

    //load or generate global config varibles
    appConfig.put("GLOBAL_CONFIG", "VALUE 1");
    return appConfig;
}

  @Bean(name = "readOnlyConfig")
  public ReadOnlyConfig getReadOnlyApplicationConfig(  @Qualifier(name = "appConfig") Map<String, String> map) {

    return new ReadOnlyConfig(map);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM