簡體   English   中英

如何在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM