Webアプリケーションで複数のSpringキャッシュマネージャーを構成し、プロジェクトのさまざまな場所で異なるキャッシュマネージャーを使用できるようにします。これを行う方法はありますか。
これを行うにはいくつかの方法があり、正しい答えはキャッシュの使用法によって異なります。
ユースケースの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であるかどうかに関係なく)があります。
私はあなたが「モジュール」に言及していることをコメントで見ました。キャッシングはインフラストラクチャの問題なので、アプリケーションレベルでその決定を移動することを強くお勧めします。キャッシュを「ローカル」としてタグ付けし、その他を「クラスター化」としてタグ付けすることができます。ただし、名前をわかりやすくするために、おそらく何らかの名前を付ける必要があります。モジュールレベルでキャッシュマネージャーを選択しないでください。
このブログ投稿 は、これを他の例で示しています。
@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
を使用しています。ただし、異なるCacheManager
sを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")
コードサンプルについては、 こちら をご覧ください。