SPR-8007
SPR-7832 + expose the invocation params through the cache root object + update javadocs
This commit is contained in:
parent
a20e73b148
commit
eb4b68ffda
|
|
@ -141,8 +141,8 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CacheOperationContext getOperationContext(CacheDefinition definition, Method method, Object[] args,
|
protected CacheOperationContext getOperationContext(CacheDefinition definition, Method method, Object[] args,
|
||||||
Class<?> targetClass) {
|
Object target, Class<?> targetClass) {
|
||||||
return new CacheOperationContext(definition, method, args, targetClass);
|
return new CacheOperationContext(definition, method, args, target, targetClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
@ -160,7 +160,7 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||||
|
|
||||||
// analyze caching information
|
// analyze caching information
|
||||||
if (cacheDef != null) {
|
if (cacheDef != null) {
|
||||||
CacheOperationContext context = getOperationContext(cacheDef, method, args, targetClass);
|
CacheOperationContext context = getOperationContext(cacheDef, method, args, target, targetClass);
|
||||||
Collection<Cache<?, ?>> caches = context.getCaches();
|
Collection<Cache<?, ?>> caches = context.getCaches();
|
||||||
|
|
||||||
if (context.hasConditionPassed()) {
|
if (context.hasConditionPassed()) {
|
||||||
|
|
@ -277,13 +277,13 @@ public abstract class CacheAspectSupport implements InitializingBean {
|
||||||
private final KeyGenerator<?> keyGenerator = CacheAspectSupport.this.keyGenerator;
|
private final KeyGenerator<?> keyGenerator = CacheAspectSupport.this.keyGenerator;
|
||||||
|
|
||||||
public CacheOperationContext(CacheDefinition operationDefinition, Method method, Object[] args,
|
public CacheOperationContext(CacheDefinition operationDefinition, Method method, Object[] args,
|
||||||
Class<?> targetClass) {
|
Object target, Class<?> targetClass) {
|
||||||
this.definition = operationDefinition;
|
this.definition = operationDefinition;
|
||||||
this.caches = CacheAspectSupport.this.getCaches(definition);
|
this.caches = CacheAspectSupport.this.getCaches(definition);
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
|
|
||||||
this.evalContext = evaluator.createEvaluationContext(caches, method, args, targetClass);
|
this.evalContext = evaluator.createEvaluationContext(caches, method, args, target, targetClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.cache.interceptor;
|
package org.springframework.cache.interceptor;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
|
|
@ -34,6 +35,34 @@ interface CacheExpressionRootObject {
|
||||||
*/
|
*/
|
||||||
String getMethodName();
|
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.
|
* Returns the caches against which the method is executed.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.cache.interceptor;
|
package org.springframework.cache.interceptor;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
|
|
@ -28,12 +29,22 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public class DefaultCacheExpressionRootObject implements CacheExpressionRootObject {
|
public class DefaultCacheExpressionRootObject implements CacheExpressionRootObject {
|
||||||
|
|
||||||
|
private final Object target;
|
||||||
|
private final Class<?> targetClass;
|
||||||
private final String methodName;
|
private final String methodName;
|
||||||
|
private final Method method;
|
||||||
private final Collection<Cache<?, ?>> caches;
|
private final Collection<Cache<?, ?>> caches;
|
||||||
|
private final Object[] args;
|
||||||
|
|
||||||
public DefaultCacheExpressionRootObject(Collection<Cache<?,?>> caches, String methodName) {
|
public DefaultCacheExpressionRootObject(Collection<Cache<?, ?>> caches, Method method, Object[] args,
|
||||||
Assert.hasText(methodName, "method name is required");
|
Object target, Class<?> targetClass) {
|
||||||
this.methodName = methodName;
|
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;
|
this.caches = caches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,4 +55,20 @@ public class DefaultCacheExpressionRootObject implements CacheExpressionRootObje
|
||||||
public Collection<Cache<?, ?>> getCaches() {
|
public Collection<Cache<?, ?>> getCaches() {
|
||||||
return caches;
|
return caches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Method getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getParams() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getTargetClass() {
|
||||||
|
return targetClass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,10 @@ class ExpressionEvaluator {
|
||||||
private Map<Method, Expression> keyCache = new ConcurrentHashMap<Method, Expression>();
|
private Map<Method, Expression> keyCache = new ConcurrentHashMap<Method, Expression>();
|
||||||
private Map<Method, Method> targetMethodCache = new ConcurrentHashMap<Method, Method>();
|
private Map<Method, Method> targetMethodCache = new ConcurrentHashMap<Method, Method>();
|
||||||
|
|
||||||
EvaluationContext createEvaluationContext(Collection<Cache<?, ?>> caches, Method method, Object[] args, Class<?> targetClass) {
|
EvaluationContext createEvaluationContext(Collection<Cache<?, ?>> caches, Method method, Object[] args,
|
||||||
DefaultCacheExpressionRootObject rootObject = new DefaultCacheExpressionRootObject(caches, method.getName());
|
Object target, Class<?> targetClass) {
|
||||||
|
DefaultCacheExpressionRootObject rootObject = new DefaultCacheExpressionRootObject(caches, method, args,
|
||||||
|
target, targetClass);
|
||||||
StandardEvaluationContext evaluationContext = new LazyParamAwareEvaluationContext(rootObject,
|
StandardEvaluationContext evaluationContext = new LazyParamAwareEvaluationContext(rootObject,
|
||||||
paramNameDiscoverer, method, args, targetClass, targetMethodCache);
|
paramNameDiscoverer, method, args, targetClass, targetMethodCache);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.aop.framework.AopProxyUtils;
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
@ -137,6 +138,16 @@ public abstract class AbstractAnnotationTest {
|
||||||
assertTrue(cache.containsKey(keyName));
|
assertTrue(cache.containsKey(keyName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testRootVars(CacheableService service) {
|
||||||
|
Object key = new Object();
|
||||||
|
Object r1 = service.rootVars(key);
|
||||||
|
assertSame(r1, service.rootVars(key));
|
||||||
|
Cache<Object, Object> cache = cm.getCache("default");
|
||||||
|
// assert the method name is used
|
||||||
|
String expectedKey = "rootVarsrootVars" + AopProxyUtils.ultimateTargetClass(service) + service;
|
||||||
|
assertTrue(cache.containsKey(expectedKey));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCacheable() throws Exception {
|
public void testCacheable() throws Exception {
|
||||||
testCacheable(cs);
|
testCacheable(cs);
|
||||||
|
|
@ -205,4 +216,14 @@ public abstract class AbstractAnnotationTest {
|
||||||
public void testClassMethodName() throws Exception {
|
public void testClassMethodName() throws Exception {
|
||||||
testMethodName(ccs, "namedefault");
|
testMethodName(ccs, "namedefault");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRootVars() throws Exception {
|
||||||
|
testRootVars(cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClassRootVars() throws Exception {
|
||||||
|
testRootVars(ccs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +56,11 @@ public class AnnotatedClassCacheableService implements CacheableService {
|
||||||
return counter.getAndIncrement();
|
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) {
|
public Object nullValue(Object arg1) {
|
||||||
nullInvocations.incrementAndGet();
|
nullInvocations.incrementAndGet();
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -40,4 +40,6 @@ public interface CacheableService<T> {
|
||||||
|
|
||||||
Number nullInvocations();
|
Number nullInvocations();
|
||||||
|
|
||||||
|
T rootVars(Object arg1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -59,6 +59,11 @@ public class DefaultCacheableService implements CacheableService<Long> {
|
||||||
return counter.getAndIncrement();
|
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")
|
@Cacheable("default")
|
||||||
public Long nullValue(Object arg1) {
|
public Long nullValue(Object arg1) {
|
||||||
nullInvocations.incrementAndGet();
|
nullInvocations.incrementAndGet();
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,30 @@ public Book findBook(String name)]]></programlisting>
|
||||||
<entry>The name of the method being invoked</entry>
|
<entry>The name of the method being invoked</entry>
|
||||||
<entry><screen>#root.methodName</screen></entry>
|
<entry><screen>#root.methodName</screen></entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>method</entry>
|
||||||
|
<entry>root object</entry>
|
||||||
|
<entry>The method being invoked</entry>
|
||||||
|
<entry><screen>#root.method.name</screen></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>target</entry>
|
||||||
|
<entry>root object</entry>
|
||||||
|
<entry>The target object being invoked</entry>
|
||||||
|
<entry><screen>#root.target</screen></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>targetClass</entry>
|
||||||
|
<entry>root object</entry>
|
||||||
|
<entry>The class of the target being invoked</entry>
|
||||||
|
<entry><screen>#root.targetClass</screen></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>params</entry>
|
||||||
|
<entry>root object</entry>
|
||||||
|
<entry>The arguments (as array) used for invoking the target</entry>
|
||||||
|
<entry><screen>#root.params[0]</screen></entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>caches</entry>
|
<entry>caches</entry>
|
||||||
<entry>root object</entry>
|
<entry>root object</entry>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue