如何在spring cache java中配置多个缓存管理器

我希望在我的Web应用程序中配置多个Spring缓存管理器,并且我可以在项目的不同位置使用不同的缓存管理器。 有没有办法做到这一点。

有几种方法可以做到这一点,正确的答案取决于您对缓存的使用。

你有一个“主”缓存管理器

如果您使用CacheManager A占用90%的用例而B使用10%,我建议为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 @EnablleCaching public class CacheConfig extends CachingConfigurerSupport { @Override public CacheResolver cacheResolver() { ... } } 

检查CacheResolver的javadoc以获取更多详细信息。 在实现中,您可能有几个CacheManager实例(无论是否为bean),您将根据您的逻辑在内部调用,以确定应使用哪个管理器。

我在评论中看到你指的是“模块”。 缓存实际上是一个基础架构问题所以我强烈建议您在应用程序级别上移动该决策。 您可以将缓存标记为“本地”,将其他标记为“群集”。 但你应该对名称有一些命名,以使其更容易。 不要在模块级别选择缓存管理器。

这篇博文通过其他例子说明了这一点。

正如@Stephane Nicoll解释的那样,你有几种选择。 我将尝试提供有关自定义CacheResolver一些信息。 CacheResolver有一个方法:

 Collection resolveCaches(CacheOperationInvocationContext context); 

它为可缓存操作的类,方法,参数等提供了上下文。

基本forms:

 public class CustomCacheResolver implements CacheResolver { private final CacheManager cacheManager; public CustomCacheResolver(CacheManager cacheManager){ this.cacheManager = cacheManager; } @Override public Collection resolveCaches(CacheOperationInvocationContext context) { Collection caches = getCaches(cacheManager, context); return caches; } private Collection 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") 

你可以在这里查看代码示例。