[英]How to have multiple cache manager configuration in multiple modules/projects spring cache java
[英]How to have multiple cache manager configuration in spring cache java
我想在我的 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 { /*...*/ }
如果您只需要為一個方法使用另一個緩存管理器,您也可以在方法級別指定
@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
有一種方法:
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());
}
}
為簡潔起見,我在這里使用了一個CacheManager
。 但是您可以將不同的CacheManager
綁定到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")
您可以在此處查看代碼示例。
您可以像這樣編寫客戶 CacheManager bean
@Primary
@Bean("customerCacheManager")
public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
Map<String, Long> expires = new HashMap<>();
expires.put("fundShareSplit", TimeUnit.SECONDS.toSeconds(60));
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setUsePrefix(true);
cacheManager.setExpires(expires);
List<String> cacheNames = Arrays.asList("fundShareSplit");
cacheManager.setCacheNames(cacheNames);
return cacheManager;
}
然后像這樣在您的注釋中使用它
@Cacheable(cacheManager = "customerCacheManager",value = "fundShareSplit",key="'smile:asset:fundSplit:fundId:'+#root.args[0]+'_localDate:'+#root.args[1]",unless="#result == null")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.