每个 *** 作所有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) { ...}
但是,在这种情况下,必须将键指定为参数。但是,您不需要特定的键,而是需要与多个键匹配的模式。所以,放弃条件,只使用…
@CacheEvictpublic 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即可插入“自定义”
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)方法内逐出的所需键执行“匹配” 。
因此,我尚未对此进行测试,但是这种(或类似方法)应该(几乎)实现您想要的(手指交叉;-)
希望这可以帮助!
干杯,约翰
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)