![](/img/trans.png)
[英]How do I tell Spring Cache to cache the exceptions in @Cacheable annotation?
[英]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即可插入“自定義” 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)
方法中逐出。
所以,我沒有測試過這個,但是這個(或類似的東西)應該達到(幾乎)你想要的東西(手指交叉;-)
希望這可以幫助!
干杯,約翰
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.