Ich möchte mehrere Spring-Cache-Manager in meiner Webanwendung konfigurieren und kann an verschiedenen Stellen in meinem Projekt verschiedene Cache-Manager verwenden. Gibt es eine Möglichkeit, dies zu tun?.
Es gibt verschiedene Möglichkeiten, dies zu tun, und die richtige Antwort hängt von Ihrer Nutzung des Caches ab.
Wenn Sie für 90% Ihres Anwendungsfalls CacheManager A und für 10% CacheManager B verwenden, würde ich empfehlen, für A ein Standard-CacheManager
zu erstellen (Sie müssen es über eine CacheConfigurerSupport
-Erweiterung angeben) ), etwas wie:
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Override
@Bean // not strictly necessary
public CacheManager cacheManager() { ... CacheManager A }
@Bean
public CacheManager bCacheManager() { ... CacheManager B }
}
Dann fügen Sie für den 10% -Anwendungsfall ein CacheConfig
am Anfang der Klassen hinzu, die den anderen Cache-Manager verwenden müssen
@CacheConfig(cacheManager="bCacheManager")
public class MyService { /*...*/ }
Wenn Sie den anderen Cache-Manager nur für eine Methode verwenden müssen, können Sie dies auch auf Methodenebene angeben
@Cacheable(cacheNames = "books", cacheManager = "bCacheManager")
public Book findById(long id) { /*...*/ }
Wenn Sie nicht in dieser Situation sind, müssen Sie wissen, welcher Cache-Manager von Fall zu Fall verwendet werden muss. Sie können dies basierend auf dem Zieltyp (MyService
) oder dem Namen des Caches (books
) tun. Sie müssen ein CacheResolver
implementieren, das diese Übersetzung für Sie ausführt.
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Override
public CacheResolver cacheResolver() { ... }
}
Überprüfen Sie das Javadoc von CacheResolver
für weitere Details. In der Implementierung gibt es möglicherweise mehrere CacheManager
Instanzen (entweder als Bean oder nicht), die Sie basierend auf Ihrer Logik intern aufrufen, um zu bestimmen, welcher Manager verwendet werden soll.
Ich habe in einem Kommentar gesehen, dass Sie sich auf "Modul" bezogen haben. Das Zwischenspeichern ist wirklich eine Infrastrukturangelegenheit, daher rate ich Ihnen dringend, diese Entscheidung auf Anwendungsebene zu verschieben. Sie können den Cache als "lokal" und andere als "geclustert" kennzeichnen. Aber Sie sollten wahrscheinlich eine Art Nomenklatur für den Namen haben, um es einfacher zu machen. Wählen Sie keinen Cache-Manager auf Modulebene.
dieser Blog-Beitrag illustriert dies anhand anderer Beispiele.
Wie @Stephane Nicoll erklärte, haben Sie mehrere Möglichkeiten. Ich werde versuchen, einige Informationen zu custom CacheResolver
zu geben. CacheResolver
hat eine Methode:
Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);
hiermit wird der Kontext der Klasse, Methode, Argumente usw. der zwischengespeicherten Operation angegeben.
In seiner Grundform:
public class CustomCacheResolver implements CacheResolver {
private final CacheManager cacheManager;
public CustomCacheResolver(CacheManager cacheManager){
this.cacheManager = cacheManager;
}
@Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
Collection<Cache> caches = getCaches(cacheManager, context);
return caches;
}
private Collection<Cache> getCaches(CacheManager cacheManager, CacheOperationInvocationContext<?> context) {
return context.getOperation().getCacheNames().stream()
.map(cacheName -> cacheManager.getCache(cacheName))
.filter(cache -> cache != null)
.collect(Collectors.toList());
}
}
Hier verwende ich der Kürze halber ein CacheManager
. Sie können jedoch verschiedene CacheManager
s an CacheResolver
binden und eine genauere Auswahl treffen: Wenn der Klassenname X
ist, verwenden Sie GuavaCacheManager
, andernfalls EhCacheCacheManager
] _.
Nach diesem Schritt sollten Sie CacheResolver
registrieren (wieder können Sie hier mehr CacheManagers
binden):
@Configuration
@EnableCaching
public class CacheConfiguration extends CachingConfigurerSupport {
@Bean
@Override
public CacheManager cacheManager() {
// Desired CacheManager
}
@Bean
@Override
public CacheResolver cacheResolver() {
return new CustomCacheResolver(cacheManager());
}
}
Und als letzten Schritt sollten Sie CustomCacheResolver
in einem von @Cacheable
, @CachePut
, @CacheConfig
usw. Anmerkungen.
@Cacheable(cacheResolver="cacheResolver")
Sie können hier nach Codebeispielen suchen.