![](/img/trans.png)
[英]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.