Toutes les annotations Spring Cache (c'est-à-dire @Cacheable
, @CacheEvict
, etc.) fonctionnent sur 1 entrée de cache par opération. @CacheEvict
prend en charge la suppression du cache entier (avec l'attribut allEntries
, mais ignore la clé dans ce cas), mais il n'est pas sélectif (capable) pour effacer un ensemble partiel d'entrées basé sur un motif de clé en une seule opération comme vous l'avez décrit .
La principale raison derrière cela est l'abstraction de l'interface Spring Cache elle-même, où la méthode evict(key:Object) prend un seul argument clé. Mais techniquement, cela dépend de l'implémentation de cache sous-jacente (par exemple GemfireCache), qui devrait supporter l'expulsion de toutes les entrées dont les clés correspondent à un motif particulier, ce qui n'est généralement pas le cas de la plupart des caches. pas Google Goyave Cache soit, voir here et here)
Cela ne veut pas dire que vous ne pouvez absolument pas atteindre votre objectif.. Ce n'est tout simplement pas quelque chose d'out-of-the-box. La chose intéressante, sans quelques problèmes techniques avec votre approche, est que votre condition réalise en quelque sorte ce que vous voulez ... une expulsion du cache ne se produit que si la clé satisfait à la condition. Cependant, votre méthode annotée @CacheEvict manque simplement la "clé", d'où l'erreur. Donc, quelque chose comme ce qui suit satisferait SPEL dans votre état ...
@CacheEvict(condition = "#key.startsWith('abc')")
public void someMethod(String key) {
...
}
Cependant, vous devez spécifier la clé comme argument dans ce cas. Mais, vous ne voulez pas de clé spécifique, vous voulez un motif correspondant à plusieurs touches. Ainsi, renoncer à la condition et il suffit d'utiliser ...
@CacheEvict
public void someMethod(String keyPattern) {
...
}
A titre d'exemple, en utilisant Goyave en tant que fournisseur de cache, vous devez maintenant fournir une implémentation « personnalisée » extension 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);
}
}
}
maintenant étendre juste le GuavaCacheManager à votre plug-in "sur mesure" GuavaCache
(CustomGuavaCache
) ...
public class CustomGuavaCacheManager extends org.springframework.cache.guava.GuavaCacheManager {
@Override
protected Cache createGuavaCache(String name) {
return new CustomGuavaCache(name, createNativeGuavaCache(name), isAllowNullValues());
}
}
Cette approche profite de la méthode Cache'sinvalidateAll(keys:Iterable) de goyave. Et, bien sûr, vous pouvez utiliser le support Regex de Java pour effectuer la "correspondance" sur les clés souhaitées à expulser à l'intérieur de la méthode isMatch(key, pattern)
.
Donc, je ne l'ai pas testé, mais cela (ou quelque chose de similaire) devrait permettre d'atteindre (presque) ce que vous voulez (les doigts croisés ;-)
Hope this helps!
Cheers, John
Question intéressante. – Scooby