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



我正在使用Spring Boot,并在应用程序启动时在@Configurationbean中加载/生成应用程序属性,并将它们放在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中注入这个属性映射,例如:

@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默认情况下会创建singleton,因此所有bean都将具有对属性映射的相同引用。然而,对简单映射的并发访问可能会产生错误。

因此,所需的更改最少

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也可以更改属性。我会创建一个新的包装器bean-around map,它只提供一种方法

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);
}

最新更新