From 469829f036e3c592d7b9af6a720b6f0b1fd3050c Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Thu, 22 Dec 2011 13:38:57 +0200 Subject: [PATCH 1/3] SPR-8983 + update documentation + add a# as an alias to p# for specifying method arguments --- .../LazyParamAwareEvaluationContext.java | 1 + .../config/AnnotatedClassCacheableService.java | 4 ++-- spring-framework-reference/src/cache.xml | 14 +++++++------- 3 files changed, 10 insertions(+), 9 deletions(-) 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 5227e43b4ce..c8c3e27905b 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/config/AnnotatedClassCacheableService.java b/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java index 573a5d8ffc1..80fa6f50e21 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/spring-framework-reference/src/cache.xml b/spring-framework-reference/src/cache.xml index f3d8b337c82..ecd688d6356 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). From 57a182380b5d9b064baae2d79416e4b713097e63 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Thu, 22 Dec 2011 14:03:12 +0200 Subject: [PATCH 2/3] SPR-8939 + properly parse key-generator on annotation-driven namespace --- .../cache/aspectj/AspectJAnnotationTest.java | 8 +++++++ .../cache/config/SomeKeyGenerator.java | 23 +++++++++++++++++++ .../cache/config/annotation-cache-aspectj.xml | 4 +++- ...tationDrivenCacheBeanDefinitionParser.java | 4 +++- 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 org.springframework.aspects/src/test/java/org/springframework/cache/config/SomeKeyGenerator.java 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 27c4e6d7d86..81a7793fc8f 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 00000000000..7c1571f39be --- /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 b91de318b09..306a2fc7827 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 26a736dd41e..5cae8fdff48 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)); } } From e72dc4d799e81f34a0fff7c51d0bc3b5141aee94 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Thu, 22 Dec 2011 15:24:23 +0200 Subject: [PATCH 3/3] SPR-8934 + add extra integration test to check for the issue (still can't reproduce it) --- .../AnnotationCacheOperationSourceTest.java | 4 + .../interceptor/ExpressionEvalutatorTest.java | 86 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 org.springframework.context/src/test/java/org/springframework/cache/interceptor/ExpressionEvalutatorTest.java 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 6f9cac9cf72..b7564dbd936 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/interceptor/ExpressionEvalutatorTest.java b/org.springframework.context/src/test/java/org/springframework/cache/interceptor/ExpressionEvalutatorTest.java new file mode 100644 index 00000000000..b52f364746a --- /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