diff --git a/org.springframework.aspects/src/test/java/org/springframework/cache/aspectj/AspectJAnnotationTest.java b/org.springframework.aspects/src/test/java/org/springframework/cache/aspectj/AspectJAnnotationTest.java
index 27c4e6d7d86f..81a7793fc8f7 100644
--- a/org.springframework.aspects/src/test/java/org/springframework/cache/aspectj/AspectJAnnotationTest.java
+++ b/org.springframework.aspects/src/test/java/org/springframework/cache/aspectj/AspectJAnnotationTest.java
@@ -16,6 +16,8 @@
package org.springframework.cache.aspectj;
+import org.junit.Assert;
+import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
@@ -30,4 +32,10 @@ public class AspectJAnnotationTest extends AbstractAnnotationTest {
protected ApplicationContext getApplicationContext() {
return new GenericXmlApplicationContext("/org/springframework/cache/config/annotation-cache-aspectj.xml");
}
+
+ @Test
+ public void testKeyStrategy() throws Exception {
+ AnnotationCacheAspect aspect = ctx.getBean("org.springframework.cache.config.internalCacheAspect", AnnotationCacheAspect.class);
+ Assert.assertSame(ctx.getBean("keyGenerator"), aspect.getKeyGenerator());
+ }
}
diff --git a/org.springframework.aspects/src/test/java/org/springframework/cache/config/SomeKeyGenerator.java b/org.springframework.aspects/src/test/java/org/springframework/cache/config/SomeKeyGenerator.java
new file mode 100644
index 000000000000..7c1571f39be5
--- /dev/null
+++ b/org.springframework.aspects/src/test/java/org/springframework/cache/config/SomeKeyGenerator.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cache.config;
+
+import org.springframework.cache.interceptor.DefaultKeyGenerator;
+
+public class SomeKeyGenerator extends DefaultKeyGenerator {
+
+}
diff --git a/org.springframework.aspects/src/test/java/org/springframework/cache/config/annotation-cache-aspectj.xml b/org.springframework.aspects/src/test/java/org/springframework/cache/config/annotation-cache-aspectj.xml
index b91de318b099..306a2fc7827d 100644
--- a/org.springframework.aspects/src/test/java/org/springframework/cache/config/annotation-cache-aspectj.xml
+++ b/org.springframework.aspects/src/test/java/org/springframework/cache/config/annotation-cache-aspectj.xml
@@ -23,7 +23,9 @@
-->
-
+
+
+
diff --git a/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java b/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java
index 26a736dd41e3..5cae8fdff480 100644
--- a/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java
+++ b/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java
@@ -76,7 +76,8 @@ private static void parseCacheManagerProperty(Element element, BeanDefinition de
* Registers a
*
*
- *
+ *
+ *
*
*
*
@@ -89,6 +90,7 @@ private void registerCacheAspect(Element element, ParserContext parserContext) {
def.setBeanClassName(CACHE_ASPECT_CLASS_NAME);
def.setFactoryMethodName("aspectOf");
parseCacheManagerProperty(element, def);
+ CacheNamespaceHandler.parseKeyGenerator(element, def);
parserContext.registerBeanComponent(new BeanComponentDefinition(def, CACHE_ASPECT_BEAN_NAME));
}
}
diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java
index 5227e43b4ce9..c8c3e27905b7 100644
--- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java
+++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java
@@ -97,6 +97,7 @@ private void loadArgsAsVariables() {
// save arguments as indexed variables
for (int i = 0; i < this.args.length; i++) {
+ setVariable("a" + i, this.args[i]);
setVariable("p" + i, this.args[i]);
}
diff --git a/org.springframework.context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTest.java b/org.springframework.context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTest.java
index 6f9cac9cf723..b7564dbd936f 100644
--- a/org.springframework.context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTest.java
+++ b/org.springframework.context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTest.java
@@ -114,6 +114,10 @@ public void singleStereotype() {
@EvictBar
public void multipleStereotype() {
}
+
+ @Caching(cacheable = { @Cacheable(value = "test", key = "a"), @Cacheable(value = "test", key = "b") })
+ public void multipleCaching() {
+ }
}
@Retention(RetentionPolicy.RUNTIME)
diff --git a/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java b/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java
index 573a5d8ffc19..80fa6f50e214 100644
--- a/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java
+++ b/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java
@@ -116,7 +116,7 @@ public Object multiCache(Object arg1) {
return counter.getAndIncrement();
}
- @Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0"), @CacheEvict(value = "primary", key = "#p0 + 'A'") })
+ @Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#a0"), @CacheEvict(value = "primary", key = "#p0 + 'A'") })
public Object multiEvict(Object arg1) {
return counter.getAndIncrement();
}
@@ -126,7 +126,7 @@ public Object multiCacheAndEvict(Object arg1) {
return counter.getAndIncrement();
}
- @Caching(cacheable = { @Cacheable(value = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
+ @Caching(cacheable = { @Cacheable(value = "primary", condition = "#a0 == 3") }, evict = { @CacheEvict("secondary") })
public Object multiConditionalCacheAndEvict(Object arg1) {
return counter.getAndIncrement();
}
diff --git a/org.springframework.context/src/test/java/org/springframework/cache/interceptor/ExpressionEvalutatorTest.java b/org.springframework.context/src/test/java/org/springframework/cache/interceptor/ExpressionEvalutatorTest.java
new file mode 100644
index 000000000000..b52f364746a4
--- /dev/null
+++ b/org.springframework.context/src/test/java/org/springframework/cache/interceptor/ExpressionEvalutatorTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cache.interceptor;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.junit.Test;
+import org.springframework.cache.Cache;
+import org.springframework.cache.annotation.AnnotationCacheOperationSource;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.cache.annotation.Caching;
+import org.springframework.cache.concurrent.ConcurrentMapCache;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.util.ReflectionUtils;
+
+import edu.emory.mathcs.backport.java.util.Collections;
+
+public class ExpressionEvalutatorTest {
+ private ExpressionEvaluator eval = new ExpressionEvaluator();
+
+ private AnnotationCacheOperationSource source = new AnnotationCacheOperationSource();
+
+ private Collection getOps(String name) {
+ Method method = ReflectionUtils.findMethod(AnnotatedClass.class, name, Object.class, Object.class);
+ return source.getCacheOperations(method, AnnotatedClass.class);
+ }
+
+ @Test
+ public void testMultipleCachingSource() throws Exception {
+ Collection ops = getOps("multipleCaching");
+ assertEquals(2, ops.size());
+ Iterator it = ops.iterator();
+ CacheOperation next = it.next();
+ assertTrue(next instanceof CacheableOperation);
+ assertTrue(next.getCacheNames().contains("test"));
+ assertEquals("#a", next.getKey());
+ next = it.next();
+ assertTrue(next instanceof CacheableOperation);
+ assertTrue(next.getCacheNames().contains("test"));
+ assertEquals("#b", next.getKey());
+ }
+
+ @Test
+ public void testMultipleCachingEval() throws Exception {
+ AnnotatedClass target = new AnnotatedClass();
+ Method method = ReflectionUtils.findMethod(AnnotatedClass.class, "multipleCaching", Object.class,
+ Object.class);
+ Object[] args = new Object[] { new Object(), new Object() };
+ Collection map = Collections.singleton(new ConcurrentMapCache("test"));
+
+ EvaluationContext evalCtx = eval.createEvaluationContext(map, method, args, target, target.getClass());
+ Collection ops = getOps("multipleCaching");
+
+ Iterator it = ops.iterator();
+
+ Object keyA = eval.key(it.next().getKey(), method, evalCtx);
+ Object keyB = eval.key(it.next().getKey(), method, evalCtx);
+
+ assertEquals(args[0], keyA);
+ assertEquals(args[1], keyB);
+ }
+
+ private static class AnnotatedClass {
+ @Caching(cacheable = { @Cacheable(value = "test", key = "#a"), @Cacheable(value = "test", key = "#b") })
+ public void multipleCaching(Object a, Object b) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-framework-reference/src/cache.xml b/spring-framework-reference/src/cache.xml
index f3d8b337c828..ecd688d63564 100644
--- a/spring-framework-reference/src/cache.xml
+++ b/spring-framework-reference/src/cache.xml
@@ -195,10 +195,10 @@ public Book findBook(String name)]]>
#root.targetClass
- params
+ args
root object
The arguments (as array) used for invoking the target
- #root.params[0]
+ #root.args[0]
caches
@@ -207,12 +207,12 @@ public Book findBook(String name)]]>
#root.caches[0].name
- parameter name
+ argument name
evaluation context
- Name of any of the method parameter. If for some reason the names are not available (ex: no debug information),
- the parameter names are also available under the ]]> where
- stands for the parameter index (starting from 0).
- iban or p0
+ Name of any of the method argument. If for some reason the names are not available (ex: no debug information),
+ the argument names are also available under the ]]> where
+ stands for the argument index (starting from 0).
+ iban or a0 (one can also use p0 or ]]> notation as an alias).