我正在使用@cacheable注解缓存函数的结果。我有3个不同的缓存,每个缓存的关键是当前登录的用户的用户ID,该用户ID与方法中的参数连接在一起。在某个事件中,我想逐出所有具有以该特定用户ID开头的键的缓存条目。例如
:
@Cacheable(value = "testCache1", key = "'abcdef'")
我希望缓存逐出注释为:
@CacheEvict(value = "getSimilarVendors", condition = "key.startsWith('abc')")
但是当我尝试实现这一点时,它给了我一个错误:
Property or field 'key' cannot be found on object of type'org.springframework.cache.interceptor.CacheExpressionRootObject' - maybe not public?
什么是实现此目的的正确方法?
每个操作所有Spring Cache批注(即@Cacheable
,@CacheEvict
等)都对1个缓存项起作用。
@CacheEvict
确实支持清除整个缓存(带有allEntries
属性,但是在这种情况下会忽略键),但是如上所述,在单个操作中基于键模式清除部分条目集不是选择性的(能够执行)。
这背后的主要原因是Spring Cache接口抽象本身,其中evict(key:Object)方法采用单个key参数。但是从技术上讲,它实际上取决于基础的Cache实现(例如GemfireCache),这将需要支持对所有键匹配特定模式的条目的逐出,通常大多数缓存都不是这种情况(例如,对于GemFire而言当然不是如此),也不适用于Google
Guava Cache;请参见此处和此处。)
这并不是说您绝对不能实现自己的目标。它不是开箱即用的东西。
有趣的是,您的方法减去了一些技术问题,就是您的条件达到了您想要的目标……只有当键满足条件时才发生缓存驱逐。但是,@
CacheEvict注释的方法只是缺少“键”,因此会出现错误。因此,类似以下内容将满足您的SpEL条件…
@CacheEvict(condition = "#key.startsWith('abc')")
public void someMethod(String key) {
...
}
但是,在这种情况下,必须将键指定为参数。但是,您不需要特定的键,而是需要与多个键匹配的模式。所以,放弃条件,只使用…
@CacheEvict
public void someMethod(String keyPattern) {
...
}
举例来说,使用Guava作为缓存提供程序,您现在需要提供一个扩展GuavaCache的“自定义”实现。
public class CustomGuavaCache extends org.springframework.cache.guava.GuavaCache {
protected boolean isMatch(String key, String pattern) {
...
}
protected boolean isPattern(String key) {
...
}
@Override
public void evict(Object key) {
if (key instanceof String && isPattern(key.toString()))) {
Map<String, Object> entries = this.cache.asMap();
Set<String> matchingKeys = new HashSet<>(entries.size());
for (String actualKey : entries.keySet()) {
if (isMatch(actualKey, key.toString()) {
matchingKeys.add(actualKey);
}
}
this.cache.invalidateAll(matchingKeys);
}
else {
this.cache.invalidate(key);
}
}
}
现在,只需扩展GuavaCacheManager即可插入“html" target="_blank">自定义”
GuavaCache
(CustomGuavaCache
)…
public class CustomGuavaCacheManager extends org.springframework.cache.guava.GuavaCacheManager {
@Override
protected Cache createGuavaCache(String name) {
return new CustomGuavaCache(name, createNativeGuavaCache(name), isAllowNullValues());
}
}
这种方法利用了Guava的Cache的
invalidateAll(keys:Iterable)方法。并且,当然,您可以使用Java的Regex支持来对要在isMatch(key, pattern)
方法内逐出的所需键执行“匹配” 。
因此,我尚未对此进行测试,但是这种(或类似方法)应该(几乎)实现您想要的(手指交叉;-)
希望这可以帮助!
干杯,约翰
我有一个简单的Quarkus资源: 我试图将实例注入到我的资源中,但是我得到了一个。但是,如果我在上使用注释,那么一切都很好。是否有一种方法可以在不使用注释的情况下将类注入到我的资源中?换句话说,是否有一种方法可以使Quakus容器可以发现而不直接注释该类? 编辑:查看CDI文档,似乎可以使用带有注释的方法手动注册bean。但是,我不清楚哪个类应该包含带注释的方法) 另一个选择是使用Jandex索
我将guava jar文件添加到类路径中,但我的IDE(eclipse)说: Nullable无法解析为类型 但如果我ctrl+单击Nullable,我会看到蓝色下划线,然后看到下划线:
我目前需要一种使用AES-128对称加密对字符串加密和字节数组解密的方法,使用C#。我找不到办法,但也许我错过了什么。
我试图了解DI在我们的代码库(Kotlin)中是如何使用的。我们正在使用googleguice进行依赖注入。 下面是一个示例类: 在模块类中: DepB类别: 据我所知,对于用< code>@Inject注释的变量,Google Guice会使用模块类来解决这些依赖关系。所以< code>DepA对象的注入方式是有意义的。 但是呢?我们如何能够在不指定任何位置的情况下注入DepB?
我正在使用Spring 4.1.4和Ehcache 2.9并使用注释进行缓存。 我注意到,每个具有带有此注释的方法的公共类都必须在 谢谢