Custom KeyGenerator

This commit adds an extra parameter to the base @Cache method
annotations: keyGenerator. This parameter holds the name of the
KeyGenerator bean to use to compute the key for that specific
caching endpoint.

This gives therefore a third way to customize the key. These are:
1. Default KeyGenerator (global for all endpoints)
2. The 'key' attribute of the annotation, giving the SpEL expression to use
3. The 'keyGenerator' attribute of the annotation

The annotation attributes are therefore exclusive. Trying to specify
them both will result in an IllegalStateException.

The KeyGenerator to use for a given operation is cached on startup
so that multiple calls to it does not resolve the instance to use over and
over again.

Issue: SPR-10629
This commit is contained in:
Stephane Nicoll
2014-01-10 16:24:51 +01:00
parent 906321dcdd
commit 81c208098f
25 changed files with 407 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@@ -105,6 +105,18 @@ public class AnnotatedClassCacheableService implements CacheableService<Object>
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", keyGenerator = "customKyeGenerator")
public Object customKeyGenerator(Object arg1) {
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", keyGenerator = "unknownBeanName")
public Object unknownCustomKeyGenerator(Object arg1) {
return counter.getAndIncrement();
}
@Override
@CachePut("default")
public Object update(Object arg1) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@@ -58,6 +58,10 @@ public interface CacheableService<T> {
T rootVars(Object arg1);
T customKeyGenerator(Object arg1);
T unknownCustomKeyGenerator(Object arg1);
T throwChecked(Object arg1) throws Exception;
T throwUnchecked(Object arg1);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@@ -109,6 +109,18 @@ public class DefaultCacheableService implements CacheableService<Long> {
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", keyGenerator = "customKeyGenerator")
public Long customKeyGenerator(Object arg1) {
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", keyGenerator = "unknownBeanName")
public Long unknownCustomKeyGenerator(Object arg1) {
return counter.getAndIncrement();
}
@Override
@CachePut("default")
public Long update(Object arg1) {

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2014 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.KeyGenerator;
import java.lang.reflect.Method;
/**
* A custom {@link KeyGenerator} that exposes the algorithm used to compute the key
* for convenience in tests scenario.
*
* @author Stephane Nicoll
*/
final class SomeCustomKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return generateKey(method.getName(), params);
}
/**
* @see #generate(Object, java.lang.reflect.Method, Object...)
*/
static Object generateKey(String methodName, Object... params) {
final StringBuilder sb = new StringBuilder(methodName);
for (Object param : params) {
sb.append(param);
}
return sb.toString();
}
}

View File

@@ -43,6 +43,8 @@
</property>
</bean>
<bean id="customKeyGenerator" class="org.springframework.cache.config.SomeCustomKeyGenerator" />
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/>
<bean id="service" class="org.springframework.cache.config.DefaultCacheableService"/>