webentwicklung-frage-antwort-db.com.de

Konfiguration mehrerer Cache-Manager im Spring-Cache java

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?.

21
Rekha

Es gibt verschiedene Möglichkeiten, dies zu tun, und die richtige Antwort hängt von Ihrer Nutzung des Caches ab.

Sie haben einen "Haupt" -Cache-Manager

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) { /*...*/ }

Feinkörnigere Auflösung

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.

33
Stephane Nicoll

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 CacheManagers 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.

5
isaolmez