我有一个使用静态缓存的类,该缓存在类的所有实例之间共享。我希望能够在运行时设置缓存的超时。
提供具体的用例:我缓存从云存储中获取的值。我想在开发环境中比在prod中更快地刷新值。部署代码时,它会获取与该环境对应的配置文件的参数。此配置文件可以包含缓存刷新时间的值。
public class Pipeline {
private static final LoadingCache<BlobId, Definitions> CACHE =
CacheBuilder.newBuilder()
.refreshAfterWrite(VALUE, TimeUnit.MINUTES) // <-- how do I set VALUE from a config file?
.build(
new CacheLoader<BlobId, Definitions>() {
public Definitions load(BlobId key) throws Exception {
return DefinitionsLoader.load(key);
}
});
...
}
答案 0 :(得分:0)
要在运行时动态加载不同的配置,您可以使用 .properties 文件。在下面的示例中,我将属性文件加载到静态块中,但您也可以在初始化缓存的静态方法中实现逻辑。
https://docs.oracle.com/javase/tutorial/essential/environment/properties.html
private static final LoadingCache<BlobId, Definitions> CACHE;
static {
Properties prop = new Properties();
try {
prop.load(new FileInputStream("config.properties"));
} catch (IOException e) {
// handle exception
}
Long value = Long.parseLong(prop.getProperty("value", "5"));
CACHE = CacheBuilder.newBuilder()
.refreshAfterWrite(value, TimeUnit.MINUTES)
.build(new CacheLoader<Integer, Definitions>() {
public Definitions load(BlobId key) throws Exception {
return DefinitionsLoader.load(key);
}
});
}
答案 1 :(得分:0)
在声明中初始化的静态字段不是为了进行参数化而设计的。
此外,您的缓存加载不灵活
如果明天你改变主意或想要使用其中的多个,你就不能。
最后,它也是不可测试的。
如果要为缓存加载提供特定行为,最自然的方法是更改包含该字段的类的API。
您可以为Pipeline
构造函数提供long delayInMnToRefresh
参数,您可以使用此参数来设置缓存的刷新时间。
public Pipeline(int delayInMnToRefresh){
CacheBuilder.newBuilder()
.refreshAfterWrite(delayInMnToRefresh, TimeUnit.MINUTES)
....
}
如果你使用Spring,你可以使用@Autowired
构造函数,它在加载Spring上下文时使用在运行时定义的属性:
@Autowired
public Pipeline(@Value("${clould.cache.delayInMnToRefresh}") int delayInMnToRefresh){
....
}
使用以这种方式定义的属性,例如在env:
中clould.cache.delayInMnToRefresh = 5
以这种方式定义的另一个属性,例如prod:
clould.cache.delayInMnToRefresh = 15
当然,您可以在没有Spring(和Spring Boot)的情况下实现此要求,但您应该执行更多的样板任务(在调用此方法之前加载属性文件并自己处理环境概念)。