JCache 创建缓存,其中包含每个键的项目列表(泛型)
JCache create cache that holds a list of items per key (Generics)
我想要一个包含项目列表的缓存。这是我的 bean 定义:
public Cache<Integer, List<Application>> getMyCacheManager(CacheManager manager) {
Cache<Integer, List<Application>> cache = manager.getCache("myCache");
if (Objects.isNull(cache)) {
var config = new MutableConfiguration<Integer, List<Application>>()
.setTypes(Integer.class, List.class)
.setStoreByValue(false)
.setStatisticsEnabled(true)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MILLISECONDS, myCacheExpiry)));
cache = manager.createCache("myCache", config);
}
return cache;
}
问题出在 .setTypes
行。在这里你必须指定缓存的键和值类型。键是直截了当的,但值是 List<Application>
类型。你不能只说:List<Application>.class
,因为那是不允许的。而且您也不能使用 List.class
,因为编译器会抱怨类型不兼容。
我真的很想保留特定类型(例如 List<Application>
),否则我每次都必须将值从 Object
转换为正确的类型。
有什么想法吗?
我不知道如何正确解决这个问题,但我可以提供一个简单的解决方案。应该可以。
public Cache<Integer, ListString> getMyCacheManager(CacheManager manager) {
Cache<Integer, ListString> cache = manager.getCache("myCache", Integer.class, ListString.class);
if (Objects.isNull(cache)) {
List<String> aa = Collections.emptyList();
MutableConfiguration<Integer, ListString> config = new MutableConfiguration<Integer, ListString>()
.setTypes(Integer.class, ListString.class)
.setStoreByValue(false)
.setStatisticsEnabled(true)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.HOURS, 1)));
cache = manager.createCache("myCache", config);
}
return cache;
}
private static final class ListString extends AbstractList<String> {
private final List<String> delegate = new LinkedList<>();
@Override
public String get(int index) {
return delegate.get(index);
}
@Override
public int size() {
return delegate.size();
}
}
JSR107/JCache 规范试图在配置中加入类型。对于集合类型,这会像您一样导致混乱。
不幸的是,您需要为要使用的正确类型添加强制转换。编译器禁止直接转换,因此您需要先转换为 Object
或 Cache
。
public Cache<Integer, List<Application>> getMyCacheManager(CacheManager manager) {
Cache<Integer, List<Application>> cache = manager.getCache("myCache");
if (Objects.isNull(cache)) {
var config = new MutableConfiguration<Integer, List<Application>>()
.setTypes(Integer.class, List.class)
.setStoreByValue(false)
.setStatisticsEnabled(true)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MILLISECONDS, myCacheExpiry)));
cache = (Cache<Integer, List<Application>>) ((Object) manager.createCache("myCache", config));
}
return cache;
}
缓存可能会检查类型或利用您提供的类型信息来进行一些优化。例如。 cache2k 将优化整数键并将键存储为原始类型,而不是对象。
缓存中的显式类型检查不是 JSR107 规范的一部分。这意味着,对于不同的 JCache 实现,您可能会或可能不会存储任何类型的对象,而不管您在配置中指定了什么。通常,按引用存储的缓存 (setStoreByValue(false)
) 存储任何对象引用而无需额外检查。后者只是不必要的开销。
JSR107 的某些部分确实谈到了运行时类型检查。这是为了确保缓存管理器返回类型兼容的缓存,而不是强制只有指定类型的对象进入缓存。服务版本中取消了严格的类型检查,因为它被证明是不切实际的。相关讨论在:https://github.com/jsr107/jsr107spec/issues/340
我想要一个包含项目列表的缓存。这是我的 bean 定义:
public Cache<Integer, List<Application>> getMyCacheManager(CacheManager manager) {
Cache<Integer, List<Application>> cache = manager.getCache("myCache");
if (Objects.isNull(cache)) {
var config = new MutableConfiguration<Integer, List<Application>>()
.setTypes(Integer.class, List.class)
.setStoreByValue(false)
.setStatisticsEnabled(true)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MILLISECONDS, myCacheExpiry)));
cache = manager.createCache("myCache", config);
}
return cache;
}
问题出在 .setTypes
行。在这里你必须指定缓存的键和值类型。键是直截了当的,但值是 List<Application>
类型。你不能只说:List<Application>.class
,因为那是不允许的。而且您也不能使用 List.class
,因为编译器会抱怨类型不兼容。
我真的很想保留特定类型(例如 List<Application>
),否则我每次都必须将值从 Object
转换为正确的类型。
有什么想法吗?
我不知道如何正确解决这个问题,但我可以提供一个简单的解决方案。应该可以。
public Cache<Integer, ListString> getMyCacheManager(CacheManager manager) {
Cache<Integer, ListString> cache = manager.getCache("myCache", Integer.class, ListString.class);
if (Objects.isNull(cache)) {
List<String> aa = Collections.emptyList();
MutableConfiguration<Integer, ListString> config = new MutableConfiguration<Integer, ListString>()
.setTypes(Integer.class, ListString.class)
.setStoreByValue(false)
.setStatisticsEnabled(true)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.HOURS, 1)));
cache = manager.createCache("myCache", config);
}
return cache;
}
private static final class ListString extends AbstractList<String> {
private final List<String> delegate = new LinkedList<>();
@Override
public String get(int index) {
return delegate.get(index);
}
@Override
public int size() {
return delegate.size();
}
}
JSR107/JCache 规范试图在配置中加入类型。对于集合类型,这会像您一样导致混乱。
不幸的是,您需要为要使用的正确类型添加强制转换。编译器禁止直接转换,因此您需要先转换为 Object
或 Cache
。
public Cache<Integer, List<Application>> getMyCacheManager(CacheManager manager) {
Cache<Integer, List<Application>> cache = manager.getCache("myCache");
if (Objects.isNull(cache)) {
var config = new MutableConfiguration<Integer, List<Application>>()
.setTypes(Integer.class, List.class)
.setStoreByValue(false)
.setStatisticsEnabled(true)
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MILLISECONDS, myCacheExpiry)));
cache = (Cache<Integer, List<Application>>) ((Object) manager.createCache("myCache", config));
}
return cache;
}
缓存可能会检查类型或利用您提供的类型信息来进行一些优化。例如。 cache2k 将优化整数键并将键存储为原始类型,而不是对象。
缓存中的显式类型检查不是 JSR107 规范的一部分。这意味着,对于不同的 JCache 实现,您可能会或可能不会存储任何类型的对象,而不管您在配置中指定了什么。通常,按引用存储的缓存 (setStoreByValue(false)
) 存储任何对象引用而无需额外检查。后者只是不必要的开销。
JSR107 的某些部分确实谈到了运行时类型检查。这是为了确保缓存管理器返回类型兼容的缓存,而不是强制只有指定类型的对象进入缓存。服务版本中取消了严格的类型检查,因为它被证明是不切实际的。相关讨论在:https://github.com/jsr107/jsr107spec/issues/340