Add custom cache manager per cache operation
It is now possible to specify the CacheManager to use per operation. The related cache annotation now has an extra attribute that defines the name of the CacheManager bean to use. The cache manager that was previously used is therefore a 'default' cache manager (i.e. the one to use if no custom cache manager has been set on the operation). Issue: SPR-8696
This commit is contained in:
@@ -28,6 +28,7 @@ import java.lang.annotation.Target;
|
||||
* a cache invalidate operation.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@@ -56,6 +57,11 @@ public @interface CacheEvict {
|
||||
*/
|
||||
String keyGenerator() default "";
|
||||
|
||||
/**
|
||||
* The bean name of the custom {@link org.springframework.cache.CacheManager} to use.
|
||||
*/
|
||||
String cacheManager() default "";
|
||||
|
||||
/**
|
||||
* Spring Expression Language (SpEL) attribute used for conditioning the method caching.
|
||||
* <p>Default is "", meaning the method is always cached.
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.cache.Cache;
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@@ -61,6 +62,11 @@ public @interface CachePut {
|
||||
*/
|
||||
String keyGenerator() default "";
|
||||
|
||||
/**
|
||||
* The bean name of the custom {@link org.springframework.cache.CacheManager} to use.
|
||||
*/
|
||||
String cacheManager() default "";
|
||||
|
||||
/**
|
||||
* Spring Expression Language (SpEL) attribute used for conditioning the cache update.
|
||||
* <p>Default is "", meaning the method result is always cached.
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@@ -59,6 +60,11 @@ public @interface Cacheable {
|
||||
*/
|
||||
String keyGenerator() default "";
|
||||
|
||||
/**
|
||||
* The bean name of the custom {@link org.springframework.cache.CacheManager} to use.
|
||||
*/
|
||||
String cacheManager() default "";
|
||||
|
||||
/**
|
||||
* Spring Expression Language (SpEL) attribute used for conditioning the method caching.
|
||||
* <p>Default is "", meaning the method is always cached.
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@@ -88,6 +89,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
|
||||
cuo.setUnless(caching.unless());
|
||||
cuo.setKey(caching.key());
|
||||
cuo.setKeyGenerator(caching.keyGenerator());
|
||||
cuo.setCacheManager(caching.cacheManager());
|
||||
cuo.setName(ae.toString());
|
||||
|
||||
checkKeySourceConsistency(ae, caching.key(), caching.keyGenerator());
|
||||
@@ -100,6 +102,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
|
||||
ceo.setCondition(caching.condition());
|
||||
ceo.setKey(caching.key());
|
||||
ceo.setKeyGenerator(caching.keyGenerator());
|
||||
ceo.setCacheManager(caching.cacheManager());
|
||||
ceo.setCacheWide(caching.allEntries());
|
||||
ceo.setBeforeInvocation(caching.beforeInvocation());
|
||||
ceo.setName(ae.toString());
|
||||
@@ -115,6 +118,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria
|
||||
cuo.setUnless(caching.unless());
|
||||
cuo.setKey(caching.key());
|
||||
cuo.setKeyGenerator(caching.keyGenerator());
|
||||
cuo.setCacheManager(caching.cacheManager());
|
||||
cuo.setName(ae.toString());
|
||||
|
||||
checkKeySourceConsistency(ae, caching.key(), caching.keyGenerator());
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.w3c.dom.Element;
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@@ -186,6 +187,8 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private String keyGenerator;
|
||||
|
||||
private String cacheManager;
|
||||
|
||||
private String condition;
|
||||
|
||||
private String method;
|
||||
@@ -197,6 +200,7 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
|
||||
String defaultCache = root.getAttribute("cache");
|
||||
key = root.getAttribute("key");
|
||||
keyGenerator = root.getAttribute("key-generator");
|
||||
cacheManager = root.getAttribute("cache-manager");
|
||||
condition = root.getAttribute("condition");
|
||||
method = root.getAttribute(METHOD_ATTRIBUTE);
|
||||
|
||||
@@ -222,6 +226,7 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
op.setKey(getAttributeValue(element, "key", this.key));
|
||||
op.setKeyGenerator(getAttributeValue(element, "key-generator", this.keyGenerator));
|
||||
op.setCacheManager(getAttributeValue(element, "cache-manager", this.cacheManager));
|
||||
op.setCondition(getAttributeValue(element, "condition", this.condition));
|
||||
|
||||
if (StringUtils.hasText(op.getKey()) && StringUtils.hasText(op.getKeyGenerator())) {
|
||||
|
||||
@@ -88,14 +88,15 @@ public abstract class CacheAspectSupport implements InitializingBean, Applicatio
|
||||
|
||||
|
||||
/**
|
||||
* Set the CacheManager that this cache aspect should delegate to.
|
||||
* Set the default {@link CacheManager} that this cache aspect should delegate to
|
||||
* if no specific cache manager has been set for the operation.
|
||||
*/
|
||||
public void setCacheManager(CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CacheManager that this cache aspect delegates to.
|
||||
* Return the default {@link CacheManager} that this cache aspect delegates to.
|
||||
*/
|
||||
public CacheManager getCacheManager() {
|
||||
return this.cacheManager;
|
||||
@@ -164,14 +165,12 @@ public abstract class CacheAspectSupport implements InitializingBean, Applicatio
|
||||
return ClassUtils.getQualifiedMethodName(specificMethod);
|
||||
}
|
||||
|
||||
protected Collection<? extends Cache> getCaches(CacheOperation operation) {
|
||||
protected Collection<? extends Cache> getCaches(CacheOperation operation, CacheManager cacheManager) {
|
||||
Set<String> cacheNames = operation.getCacheNames();
|
||||
Collection<Cache> caches = new ArrayList<Cache>(cacheNames.size());
|
||||
for (String cacheName : cacheNames) {
|
||||
Cache cache = this.cacheManager.getCache(cacheName);
|
||||
if (cache == null) {
|
||||
throw new IllegalArgumentException("Cannot find cache named '" + cacheName + "' for " + operation);
|
||||
}
|
||||
Cache cache = cacheManager.getCache(cacheName);
|
||||
Assert.notNull(cache, "Cannot find cache named '" + cacheName + "' for " + operation);
|
||||
caches.add(cache);
|
||||
}
|
||||
return caches;
|
||||
@@ -386,6 +385,8 @@ public abstract class CacheAspectSupport implements InitializingBean, Applicatio
|
||||
|
||||
private final KeyGenerator operationKeyGenerator;
|
||||
|
||||
private final CacheManager operationCacheManager;
|
||||
|
||||
public CacheOperationContext(CacheOperation operation, Method method,
|
||||
Object[] args, Object target, Class<?> targetClass) {
|
||||
this.operation = operation;
|
||||
@@ -393,13 +394,20 @@ public abstract class CacheAspectSupport implements InitializingBean, Applicatio
|
||||
this.args = extractArgs(method, args);
|
||||
this.target = target;
|
||||
this.targetClass = targetClass;
|
||||
this.caches = CacheAspectSupport.this.getCaches(operation);
|
||||
if (StringUtils.hasText(operation.getKeyGenerator())) { // TODO: exception mgt?
|
||||
this.operationKeyGenerator = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
|
||||
applicationContext, KeyGenerator.class, operation.getKeyGenerator());
|
||||
} else {
|
||||
this.operationKeyGenerator = keyGenerator;
|
||||
}
|
||||
if (StringUtils.hasText(operation.getCacheManager())) {
|
||||
this.operationCacheManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
|
||||
applicationContext, CacheManager.class, operation.getCacheManager());
|
||||
}
|
||||
else {
|
||||
this.operationCacheManager = cacheManager;
|
||||
}
|
||||
this.caches = CacheAspectSupport.this.getCaches(operation, operationCacheManager);
|
||||
}
|
||||
|
||||
private Object[] extractArgs(Method method, Object[] args) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.util.Assert;
|
||||
* Base class for cache operations.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public abstract class CacheOperation {
|
||||
|
||||
@@ -37,6 +38,8 @@ public abstract class CacheOperation {
|
||||
|
||||
private String keyGenerator = "";
|
||||
|
||||
private String cacheManager = "";
|
||||
|
||||
private String name = "";
|
||||
|
||||
|
||||
@@ -56,6 +59,10 @@ public abstract class CacheOperation {
|
||||
return keyGenerator;
|
||||
}
|
||||
|
||||
public String getCacheManager() {
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -88,6 +95,11 @@ public abstract class CacheOperation {
|
||||
this.keyGenerator = keyGenerator;
|
||||
}
|
||||
|
||||
public void setCacheManager(String cacheManager) {
|
||||
Assert.notNull(cacheManager);
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
Assert.hasText(name);
|
||||
this.name = name;
|
||||
@@ -137,6 +149,8 @@ public abstract class CacheOperation {
|
||||
result.append(this.key);
|
||||
result.append("' | keyGenerator='");
|
||||
result.append(this.keyGenerator);
|
||||
result.append("' | cacheManager='");
|
||||
result.append(this.cacheManager);
|
||||
result.append("' | condition='");
|
||||
result.append(this.condition);
|
||||
result.append("'");
|
||||
|
||||
Reference in New Issue
Block a user