如何在spring cache java中配置多个缓存管理器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38570211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to have multiple cache manager configuration in spring cache java
提问by Rekha
I want to have multiple spring cache managers configured in my web-application and I would be able to use different cache manager at various places in my project. Is there any way to do this.
我想在我的 web 应用程序中配置多个 spring 缓存管理器,我将能够在我的项目的不同位置使用不同的缓存管理器。有没有办法做到这一点。
回答by Stephane Nicoll
There are several ways you can do this and the right answer depends on your usage of the cache.
有几种方法可以做到这一点,正确的答案取决于您对缓存的使用。
You have a "main" cache manager
你有一个“主”缓存管理器
If you use CacheManager A for 90% of your use case and B for 10% I'd advise to create a default CacheManager
for A (you'll need to specify it via a CacheConfigurerSupport
extension), something like:
如果您在 90% 的用例中使用 CacheManager A 而在 10% 中使用 B,我建议CacheManager
为 A创建一个默认值(您需要通过CacheConfigurerSupport
扩展指定它),例如:
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Override
@Bean // not strictly necessary
public CacheManager cacheManager() { ... CacheManager A }
@Bean
public CacheManager bCacheManager() { ... CacheManager B }
}
Then for the 10% use case you add a CacheConfig
at the top of the classes that need to use the other cache manager
然后对于 10% 的用例,您CacheConfig
在需要使用其他缓存管理器的类的顶部添加
@CacheConfig(cacheManager="bCacheManager")
public class MyService { /*...*/ }
If you need to use the other cache manager for only one method, you can specify that at method level as well
如果您只需要为一个方法使用另一个缓存管理器,您也可以在方法级别指定
@Cacheable(cacheNames = "books", cacheManager = "bCacheManager")
public Book findById(long id) { /*...*/ }
More fine grained resolution
更细粒度的分辨率
If you're not in this situation, you need a way to know which cache manager needs to be used on a case-by-case basis. You can do that based on the target type (MyService
) or the name of the cache (books
). You'll need to implement a CacheResolver
that does that translation for you.
如果您不是这种情况,则需要一种方法来了解需要根据具体情况使用哪个缓存管理器。您可以根据目标类型 ( MyService
) 或缓存名称 ( books
) 执行此操作。你需要实现一个CacheResolver
为你做翻译的。
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
@Override
public CacheResolver cacheResolver() { ... }
}
Check the javadoc of CacheResolver
for more details. In the implementation, you may have several CacheManager
instances (either as bean or not) that you'll call internally based on your logic to determine which manager should be used.
查看 的 javadoc 以CacheResolver
获取更多详细信息。在实现中,您可能有多个CacheManager
实例(无论是否作为 bean),您将根据您的逻辑在内部调用它们以确定应该使用哪个管理器。
I saw in a comment that you were referring to "module". Caching is really an infrastructure matter so I'd strongly advice you to move that decision at the application level. You may tag cache as being "local" and others being "clustered". But you should probably have some kind of nomenclature for the name to make it easier. Don't choose a cache manager at the module level.
我在评论中看到您指的是“模块”。缓存实际上是一个基础架构问题,因此我强烈建议您在应用程序级别移动该决定。您可以将缓存标记为“本地”,而将其他缓存标记为“集群”。但是您可能应该为名称使用某种命名法,以使其更容易。不要在模块级别选择缓存管理器。
this blog postillustrates this with other examples.
这篇博文用其他例子说明了这一点。
回答by isaolmez
As @Stephane Nicoll explained, you have several options.
I will try to give some info on custom CacheResolver
. CacheResolver
has one method:
正如@Stephane Nicoll 所解释的,您有多种选择。我会尝试提供一些关于 custom 的信息CacheResolver
。CacheResolver
有一种方法:
Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context);
which gives context to the cacheable operation's class, method, arguments etc.
它为可缓存操作的类、方法、参数等提供上下文。
In its basic form:
在其基本形式中:
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());
}
}
Here I am using one CacheManager
for brevity. But you can bind different CacheManager
s to CacheResolver
and make more granular selections: if class name is X
, then use GuavaCacheManager
, otherwise use EhCacheCacheManager
.
CacheManager
为简洁起见,我在这里使用了一个。但是您可以将不同的CacheManager
s绑定到CacheResolver
并进行更精细的选择:如果类名是X
,则使用GuavaCacheManager
,否则使用EhCacheCacheManager
。
After this step, you should register CacheResolver
, (again you can bind more CacheManagers
here):
在这一步之后,你应该注册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());
}
}
And as the last step, you should specify CustomCacheResolver
in one of @Cacheable
, @CachePut
, @CacheConfig
etc. annotations.
而作为最后一步,你应该指定CustomCacheResolver
于一体@Cacheable
,@CachePut
,@CacheConfig
等注释。
@Cacheable(cacheResolver="cacheResolver")
You can look herefor code samples.
您可以在此处查看代码示例。