问题
We use Spring cache framework for caching, and we'd like to able to support multiple namespaces for caches, such as "book", or "isbn", with the cache namespaces being configurable, rather than hardcoded in the class, like, instead of having
@Cacheable({ "book","isbn"})
public Book findBook(ISBN isbn) {...}
we want to be able somehow inject the cache name from a properties file, so that the cache name can be dynamically set, like:
@Cacheable({ #cachename1, #cachename2})
public Book findBook(ISBN isbn) {...}
I'm using SpEL here, but don't know if this is doable at all.
回答1:
Spring 4.1 introduces CacheResolver
, and use your self defined CacheResolver
to select Cache
then can be dynamic. spring 4.1 cache impovements
回答2:
Going off smartwjw's answer...
I was looking to have cacheNames resolved via spring environment variables, such as @Cacheable("${my.config.property.name}")
. I accomplished this via a custom CacheResolver
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.SimpleCacheResolver;
import org.springframework.core.env.PropertyResolver;
public class PropertyResolvingCacheResolver
extends SimpleCacheResolver {
private final PropertyResolver propertyResolver;
protected PropertyResolvingCacheResolver(CacheManager cacheManager, PropertyResolver propertyResolver) {
super(cacheManager);
this.propertyResolver = propertyResolver;
}
@Override
protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
Collection<String> unresolvedCacheNames = super.getCacheNames(context);
return unresolvedCacheNames.stream()
.map(unresolvedCacheName -> propertyResolver.resolveRequiredPlaceholders(unresolvedCacheName)).collect(Collectors.toList());
}
}
And then of course you must configure it as THE CacheResolver
to use with a @Configuration
that extends org.springframework.cache.annotation.CachingConfigurerSupport
.
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
public static final String PROPERTY_RESOLVING_CACHE_RESOLVER_BEAN_NAME = "propertyResolvingCacheResolver";
@Autowired
private CacheManager cacheManager;
@Autowired
private Environment springEnv;
@Bean(PROPERTY_RESOLVING_CACHE_RESOLVER_BEAN_NAME)
@Override
public CacheResolver cacheResolver() {
return new PropertyResolvingCacheResolver(cacheManager, springEnv);
}
}
回答3:
Nope, dynamic (SpEL or otherwise) expressions are not supported for the cache name (value
) property of the @Cacheable annotation. You would have to implement your own version of the org.springframework.cache.annotation.SpringCacheAnnotationParser
and get it injected into the framework.
回答4:
you can also use the cache directly, makes all even more predictable
EhCacheCacheManager cacheManager = (EhCacheCacheManager) CDBBeanFactory.instance().getBean("cacheManager");
CacheManager manager cacheManager.getCacheManager();
manager.getCache("cacheBin").get("key");
manager.getCache("cacheBin").put(new Element(key, obj));
etc ..
来源:https://stackoverflow.com/questions/13189814/how-can-i-make-the-cache-name-in-spring-cache-configurable