2016-07-25 14 views
11

Ich möchte mehrere Feder-Cache-Manager in meiner Web-Anwendung konfiguriert haben, und ich könnte verschiedene Cache-Manager an verschiedenen Stellen in meinem Projekt verwenden. Gibt es einen Weg dies zu tun?Wie man mehrere Cache-Manager-Konfiguration im Frühjahr Cache java

+0

Was Sie bisher herausgefunden haben? –

+0

Ich habe EHCacheManager in einem der Module meines Projekts konfiguriert, jetzt möchte ich RedisCacheManager in einem anderen Modul verwenden, aber Spring erlaubt nicht, zwei Beans vom CacheManager-Typ in einem einzelnen Anwendungskontext zu haben. Dann habe ich CachingConfigurer in meiner Konfigurationsklasse implementiert vermeide dieses Problem. aber am Ende habe ich nur CacheManager-Bean auf Typ-EHCacheManager in meinem ApplicationContext. Aber meine Anforderung ist, dass beide cacheManagers-Bean erstellt werden und ich in der Lage sein sollte, beide in verschiedenen Modulen zu verwenden. Ich habe gehört, über CompositeCacheManager, nicht sicher, dass die Hilfe hier oder nicht. Vielen Dank – Rekha

Antwort

16

Es gibt mehrere Möglichkeiten, wie Sie dies tun können und die richtige Antwort hängt von Ihrer Verwendung des Caches ab.

Sie haben einen „Haupt“ Cache-Manager

Wenn Sie Cachemanager A für 90% des Anwendungsfalles und B für 10% verwenden ich raten würde ein Standard-CacheManager für A zu erstellen (Sie müssen zu geben sie über eine CacheConfigurerSupport Erweiterung), so etwas wie:

@Configuration 
@EnablleCaching 
public class CacheConfig extends CachingConfigurerSupport { 

    @Override 
    @Bean // not strictly necessary 
    public CacheManager cacheManager() { ... CacheManager A } 

    @Bean 
    public CacheManager bCacheManager() { ... CacheManager B } 
} 

Dann für die 10% Verwendung Fall, dass Sie eine CacheConfig an der Spitze der Klassen hinzufügen, dass die anderen Cache-Manager

@CacheConfig(cacheManager="bCacheManager") 
public class MyService { ... } 
verwenden müssen

Wenn Sie den anderen Cache-Manager für nur eine Methode verwenden, dann können Sie, dass bei Verfahren Ebene angeben und

@Cacheable(cacheNames = "books", cacheManager = "bCacheManager") 
public Book findById(long id) { ... } 

Mehr feinkörnige Auflösung

Wenn Sie nicht in dieser Situation sind, können Sie Sie müssen 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 eine CacheResolver implementieren, die diese Übersetzung für Sie übernimmt.

@Configuration 
@EnablleCaching 
public class CacheConfig extends CachingConfigurerSupport { 

    @Override 
    public CacheResolver cacheResolver() { ... } 
} 

Überprüfen Sie die javadoc von CacheResolver für weitere Details. In der Implementierung verfügen Sie möglicherweise über mehrere CacheManager Instanzen (entweder als Bean oder nicht), die Sie basierend auf Ihrer Logik intern aufrufen, um festzustellen, welcher Manager verwendet werden soll.

Ich sah in einem Kommentar, dass Sie sich auf "Modul" beziehen. Caching ist wirklich eine Frage der Infrastruktur, daher rate ich Ihnen dringend, diese Entscheidung auf Anwendungsebene zu verschieben. Sie können den Cache als "lokal" und andere als "gruppiert" markieren. 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.

this blog post veranschaulicht dies mit anderen Beispielen.

+0

Stephane, ich folgen diesem Ansatz zu Spring Boot Standardkonfiguration zu erweitern, aber es scheint eine rohe Ansatz für mein Problem, können Sie mir einen besseren Weg vorschlagen lösen [mein Problem] (http://stackoverflow.com/q/43500863/1061499)? danke – davioooh

+0

aufgepasst: Im Frühling-Boot 1.5, wenn Sie CachingConfigurerSupport erweitern, überschreiben Sie einige Methoden (default keyGenerator und errorHandler), die Ihren Cache unbrauchbar machen würden. Ich habe den gleichen Ansatz verwendet, ohne diese Klasse zu erweitern. Es genügt, die Beans zu deklarieren, damit es funktioniert. – dnul

+0

Sie müssen diese Methoden nicht überschreiben. Wenn Sie dies nicht tun, werden die Standardnamen 'KeyGenerator' und' ErrorHandler' verwendet. –

1

Wie @ Stephane Nicoll erklärte, haben Sie mehrere Möglichkeiten. Ich werde versuchen, einige Informationen über benutzerdefinierte CacheResolver zu geben. CacheResolver hat eine Methode:

Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context); 

die Kontext der zwischenspeicherbar Betrieb der Klasse, Methode Argumente usw.

In seiner Grundform gibt:

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 bin ich mit einem Cachemanager der Kürze . Sie können jedoch verschiedene CacheManager an CacheResolver binden und eine genauere Auswahl treffen: Wenn der Klassenname X ist, verwenden Sie GuavaCacheManager, andernfalls verwenden Sie EhCacheCacheManager.

Nach diesem Schritt sollten Sie sich registrieren CacheResolver, (wieder können Sie mehr Cachemanager hier 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 der @Cacheable, @CachePut, geben Sie @ CacheConfig etc. Anmerkungen.

@Cacheable(cacheResolver="cacheResolver") 

Sie können here sucht Codebeispiele