web-dev-qa-db-ja.com

Spring Cacheに複数のキャッシュマネージャーを設定する方法java

Webアプリケーションで複数のSpringキャッシュマネージャーを構成し、プロジェクトのさまざまな場所で異なるキャッシュマネージャーを使用できるようにします。これを行う方法はありますか。

21
Rekha

これを行うにはいくつかの方法があり、正しい答えはキャッシュの使用法によって異なります。

「メイン」キャッシュマネージャーがあります

ユースケースの90%でCacheManager Aを使用し、10%でBを使用する場合、AのデフォルトCacheManagerを作成することをお勧めします(CacheConfigurerSupport拡張子で指定する必要があります) )、 何かのようなもの:

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {

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

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

次に、10%のユースケースでは、他のキャッシュマネージャーを使用する必要があるクラスの先頭にCacheConfigを追加します

@CacheConfig(cacheManager="bCacheManager")
public class MyService { /*...*/ }

1つのメソッドのみに他のキャッシュマネージャーを使用する必要がある場合は、メソッドレベルでも指定できます。

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

より細かな解像度

この状況にない場合は、どのキャッシュマネージャーをケースバイケースで使用する必要があるかを知る方法が必要です。これは、ターゲットタイプ(MyService)またはキャッシュの名前(books)に基づいて実行できます。変換を行うCacheResolverを実装する必要があります。

@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {

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

詳細については、CacheResolverのjavadocを確認してください。実装では、使用するマネージャーを決定するためにロジックに基づいて内部的に呼び出すいくつかのCacheManagerインスタンス(Beanであるかどうかに関係なく)があります。

私はあなたが「モジュール」に言及していることをコメントで見ました。キャッシングはインフラストラクチャの問題なので、アプリケーションレベルでその決定を移動することを強くお勧めします。キャッシュを「ローカル」としてタグ付けし、その他を「クラスター化」としてタグ付けすることができます。ただし、名前をわかりやすくするために、おそらく何らかの名前を付ける必要があります。モジュールレベルでキャッシュマネージャーを選択しないでください。

このブログ投稿 は、これを他の例で示しています。

33
Stephane Nicoll

@Stephane Nicollが説明したように、いくつかのオプションがあります。カスタムCacheResolverに関する情報を提供しようとします。 CacheResolverには1つのメソッドがあります:

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

キャッシュ可能な操作のクラス、メソッド、引数などにコンテキストを提供します。

基本的な形式では:

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());
    }
}

ここでは、簡潔にするために1つのCacheManagerを使用しています。ただし、異なるCacheManagersをCacheResolverにバインドし、より詳細な選択を行うことができます。クラス名がXの場合はGuavaCacheManagerを使用し、そうでない場合はEhCacheCacheManager

このステップの後、CacheResolverを登録する必要があります(ここでもCacheManagersをさらにバインドできます)。

@Configuration
@EnableCaching
public class CacheConfiguration extends CachingConfigurerSupport {

    @Bean
    @Override
    public CacheManager cacheManager() {
        // Desired CacheManager
    }

    @Bean
    @Override
    public CacheResolver cacheResolver() {
        return new CustomCacheResolver(cacheManager());
    }
}

最後のステップとして、@Cacheable@CachePut@CacheConfigなどの注釈のいずれかでCustomCacheResolverを指定する必要があります。

@Cacheable(cacheResolver="cacheResolver")

コードサンプルについては、 こちら をご覧ください。

5
isaolmez