繁体   English   中英

如何在Cacheable注释中使用该键

[英]How do I use the key, in a condition in Cacheable annotation

我正在使用@cacheable注释来缓存函数的结果。 我有3个不同的缓存,每个缓存的关键是当前登录用户的用户ID与方法中的参数连接。 在某个事件中,我想要驱逐所有具有以该特定用户ID开头的密钥的缓存条目。 例如 :

@Cacheable(value = "testCache1", key = "'abcdef'")

我想缓存evict注释是这样的:

@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)方法采用单个键参数。 但从技术上讲,它实际上取决于底层的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即可插入“自定义” GuavaCacheCustomGuavaCache )...

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)方法中逐出。

所以,我没有测试过这个,但是这个(或类似的东西)应该达到(几乎)你想要的东西(手指交叉;-)

希望这可以帮助!

干杯,约翰

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM