From a653a50be8f255b5eb451a72c286af08993eb091 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Mon, 28 Mar 2011 11:36:05 +0000 Subject: [PATCH] SPR-8007 SPR-7832 + expose the invocation params through the cache root object + update javadocs git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4114 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../cache/interceptor/CacheAspectSupport.java | 10 +++--- .../CacheExpressionRootObject.java | 29 ++++++++++++++++ .../DefaultCacheExpressionRootObject.java | 33 +++++++++++++++++-- .../interceptor/ExpressionEvaluator.java | 6 ++-- .../cache/config/AbstractAnnotationTest.java | 21 ++++++++++++ .../AnnotatedClassCacheableService.java | 5 +++ .../cache/config/CacheableService.java | 2 ++ .../cache/config/DefaultCacheableService.java | 5 +++ spring-framework-reference/src/cache.xml | 24 ++++++++++++++ 9 files changed, 125 insertions(+), 10 deletions(-) diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java index b1c7b721c60..25e5a3f383e 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java @@ -141,8 +141,8 @@ public abstract class CacheAspectSupport implements InitializingBean { } protected CacheOperationContext getOperationContext(CacheDefinition definition, Method method, Object[] args, - Class targetClass) { - return new CacheOperationContext(definition, method, args, targetClass); + Object target, Class targetClass) { + return new CacheOperationContext(definition, method, args, target, targetClass); } @SuppressWarnings("unchecked") @@ -160,7 +160,7 @@ public abstract class CacheAspectSupport implements InitializingBean { // analyze caching information if (cacheDef != null) { - CacheOperationContext context = getOperationContext(cacheDef, method, args, targetClass); + CacheOperationContext context = getOperationContext(cacheDef, method, args, target, targetClass); Collection> caches = context.getCaches(); if (context.hasConditionPassed()) { @@ -277,13 +277,13 @@ public abstract class CacheAspectSupport implements InitializingBean { private final KeyGenerator keyGenerator = CacheAspectSupport.this.keyGenerator; public CacheOperationContext(CacheDefinition operationDefinition, Method method, Object[] args, - Class targetClass) { + Object target, Class targetClass) { this.definition = operationDefinition; this.caches = CacheAspectSupport.this.getCaches(definition); this.method = method; this.args = args; - this.evalContext = evaluator.createEvaluationContext(caches, method, args, targetClass); + this.evalContext = evaluator.createEvaluationContext(caches, method, args, target, targetClass); } /** diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java index 5104b34c117..9bdaf97c29f 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java @@ -16,6 +16,7 @@ package org.springframework.cache.interceptor; +import java.lang.reflect.Method; import java.util.Collection; import org.springframework.cache.Cache; @@ -34,6 +35,34 @@ interface CacheExpressionRootObject { */ String getMethodName(); + /** + * Returns the method being cached. + * + * @return method being cached + */ + Method getMethod(); + + /** + * Returns the parameters for this invocation. + * + * @return params for this invocation. + */ + Object[] getParams(); + + /** + * Returns the target instance being cached. + * + * @return target instance + */ + Object getTarget(); + + /** + * Returns the target class. + * + * @return target class + */ + Class getTargetClass(); + /** * Returns the caches against which the method is executed. * diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java index 28dd61bfe8c..6262604c624 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java @@ -16,6 +16,7 @@ package org.springframework.cache.interceptor; +import java.lang.reflect.Method; import java.util.Collection; import org.springframework.cache.Cache; @@ -28,12 +29,22 @@ import org.springframework.util.Assert; */ public class DefaultCacheExpressionRootObject implements CacheExpressionRootObject { + private final Object target; + private final Class targetClass; private final String methodName; + private final Method method; private final Collection> caches; + private final Object[] args; - public DefaultCacheExpressionRootObject(Collection> caches, String methodName) { - Assert.hasText(methodName, "method name is required"); - this.methodName = methodName; + public DefaultCacheExpressionRootObject(Collection> caches, Method method, Object[] args, + Object target, Class targetClass) { + Assert.notNull(method, "method is required"); + Assert.notNull(targetClass, "targetClass is required"); + this.method = method; + this.methodName = method.getName(); + this.target = target; + this.targetClass = targetClass; + this.args = args; this.caches = caches; } @@ -44,4 +55,20 @@ public class DefaultCacheExpressionRootObject implements CacheExpressionRootObje public Collection> getCaches() { return caches; } + + public Method getMethod() { + return method; + } + + public Object[] getParams() { + return args; + } + + public Object getTarget() { + return target; + } + + public Class getTargetClass() { + return targetClass; + } } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java index 1ae22214172..3d216b519d4 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java @@ -47,8 +47,10 @@ class ExpressionEvaluator { private Map keyCache = new ConcurrentHashMap(); private Map targetMethodCache = new ConcurrentHashMap(); - EvaluationContext createEvaluationContext(Collection> caches, Method method, Object[] args, Class targetClass) { - DefaultCacheExpressionRootObject rootObject = new DefaultCacheExpressionRootObject(caches, method.getName()); + EvaluationContext createEvaluationContext(Collection> caches, Method method, Object[] args, + Object target, Class targetClass) { + DefaultCacheExpressionRootObject rootObject = new DefaultCacheExpressionRootObject(caches, method, args, + target, targetClass); StandardEvaluationContext evaluationContext = new LazyParamAwareEvaluationContext(rootObject, paramNameDiscoverer, method, args, targetClass, targetMethodCache); diff --git a/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTest.java b/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTest.java index 5709d5c1070..3ba54a5a4fc 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; +import org.springframework.aop.framework.AopProxyUtils; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.context.ApplicationContext; @@ -137,6 +138,16 @@ public abstract class AbstractAnnotationTest { assertTrue(cache.containsKey(keyName)); } + public void testRootVars(CacheableService service) { + Object key = new Object(); + Object r1 = service.rootVars(key); + assertSame(r1, service.rootVars(key)); + Cache cache = cm.getCache("default"); + // assert the method name is used + String expectedKey = "rootVarsrootVars" + AopProxyUtils.ultimateTargetClass(service) + service; + assertTrue(cache.containsKey(expectedKey)); + } + @Test public void testCacheable() throws Exception { testCacheable(cs); @@ -205,4 +216,14 @@ public abstract class AbstractAnnotationTest { public void testClassMethodName() throws Exception { testMethodName(ccs, "namedefault"); } + + @Test + public void testRootVars() throws Exception { + testRootVars(cs); + } + + @Test + public void testClassRootVars() throws Exception { + testRootVars(ccs); + } } \ No newline at end of file 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 d3e2cbabc89..ac851832e81 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 @@ -56,6 +56,11 @@ public class AnnotatedClassCacheableService implements CacheableService { return counter.getAndIncrement(); } + @Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target") + public Object rootVars(Object arg1) { + return counter.getAndIncrement(); + } + public Object nullValue(Object arg1) { nullInvocations.incrementAndGet(); return null; diff --git a/org.springframework.context/src/test/java/org/springframework/cache/config/CacheableService.java b/org.springframework.context/src/test/java/org/springframework/cache/config/CacheableService.java index 34f5e164ea8..707ff972491 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/config/CacheableService.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/config/CacheableService.java @@ -40,4 +40,6 @@ public interface CacheableService { Number nullInvocations(); + T rootVars(Object arg1); + } \ No newline at end of file diff --git a/org.springframework.context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java b/org.springframework.context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java index 4c9134a6ed3..3e9db797102 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java @@ -59,6 +59,11 @@ public class DefaultCacheableService implements CacheableService { return counter.getAndIncrement(); } + @Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target") + public Long rootVars(Object arg1) { + return counter.getAndIncrement(); + } + @Cacheable("default") public Long nullValue(Object arg1) { nullInvocations.incrementAndGet(); diff --git a/spring-framework-reference/src/cache.xml b/spring-framework-reference/src/cache.xml index 7ea610ed26e..b1a3ac9b1c2 100644 --- a/spring-framework-reference/src/cache.xml +++ b/spring-framework-reference/src/cache.xml @@ -176,6 +176,30 @@ public Book findBook(String name)]]> The name of the method being invoked #root.methodName + + method + root object + The method being invoked + #root.method.name + + + target + root object + The target object being invoked + #root.target + + + targetClass + root object + The class of the target being invoked + #root.targetClass + + + params + root object + The arguments (as array) used for invoking the target + #root.params[0] + caches root object