我们正在尝试在Java中创建Cache
的基本实现。为此,我们创建了一个注释@Cached
,定义为:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Cached {
<T> Class<T> keyClass();
<V> Class<V> valueClass();
String cacheId();
}
这将导致错误:
@interface members may not have type parameters
。但是,这是必需的,因为我们希望转换返回的方法的值并将其存储在缓存中。我们正在使用AspectJ
截获需要缓存其结果的方法调用。我们可以获得结果的另一种方式是什么?由于并非所有方法都具有相同的签名,因此我们必须依靠标记为
@Cached
的方法来实现我们的缓存。更新
这是将数据存储在缓存中的类:
public class Cache<K extends Serializable, V> {
private Map<K, CacheEntry<V> cache;
// Some other fields and accessors
}
CacheEntry
类的定义为:public class CacheEntry<V> {
private V value;
// Some other fields used for invalidating the cache entry and accessors
}
现在,当访问缓存时,我想做这样的事情:
cache.getCache().values().stream()
.map(value -> cached.valueClass().cast(value))
.collect(Collectors.toList());
在上面的代码中,
cached
是方法中使用的@Cached
批注的引用,如下所示:@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
List<Person> findAll();
最佳答案
在这种情况下,cached.valueClass().cast(value)
无法为您提供帮助,主要是因为编译器无法强制cached.valueClass()
与Cached.valueClass()
兼容。
使用类型转换帮助缓存客户端的最佳方法是让它们在读取时指定目标类型:
public <V> List<V> getAllCachedValues(Class<V> valueClass) {
return cache.getCache().values().stream()
.map(value -> valueClass.cast(value))
.collect(Collectors.toList());
}
或与此未经检查的演员:
public <V> List<V> getAllCachedValues() {
return cache.getCache().values().stream()
.map(value -> (V) value)
.collect(Collectors.toList());
}
以下是一些用法,用于说明尝试使用注释强制执行类型安全性是多么不现实:
@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
List<Banana> findAll();
T
和V
(否则,这将毫无意义,对吧?)。话虽如此,这是可能的:@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
//and then
Cache<Long, Banana> cacheInstance = cacheManager.getCache("personCache");
当然,您可以将
Class
参数添加到getCache
:Cache<Long, Banana> cacheInstance = cacheManager.getCache("personCache",
Long.class, Banana.class);
并使用实际的
Class
实例进行验证。但是,当您可以采用第一种方法(在检索时进行广播)时,这样做的目的是什么?最重要的是,调用者最终将确保类型兼容性,而注释元数据则无济于事。 我认为,如果您要将缓存的值序列化为JSON和XML等格式,并且需要原始类来在缓存被命中时反序列化它们(当然,希望客户端进行转换),那么
@Cached(keyClass = Long.class, valueClass = Person.class, cacheId = "personCache")
可能会有助于输入。关于java - 使用Class <T>作为Java中注释的属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58518232/