使用命令行参数初始化静态缓存



我有一个类,它使用在该类的所有实例之间共享的静态缓存。我希望能够在运行时设置缓存的超时。

为了提供一个具体的用例:我缓存从云存储中获取的值。我想在开发环境中比在生产环境中更快地刷新值。部署代码时,它为与该环境对应的配置文件获取参数。此配置文件可以包含缓存刷新时间的值。

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

要在运行时动态加载不同的配置,可以使用.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);
}
});
}

在其声明中初始化的静态字段不是为了按照您想要的方式进行参数化而设计的。

此外,您的缓存加载并不灵活。
如果明天你改变主意或你想使用其中的多个,你不能。
最后,它也是不可测试的。

如果要为缓存加载提供特定行为,最自然的方法是更改包含字段的类的 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)的情况下实现这个需求,但你应该简单地执行更多的样板任务(在调用此方法之前加载属性文件并处理环境的概念)。

最新更新