polishing

This commit is contained in:
Stephane Nicoll 2014-07-23 17:08:19 +02:00
parent 5be1ff281c
commit d9e0b292ab
53 changed files with 434 additions and 294 deletions

View File

@ -29,8 +29,8 @@ import javax.cache.annotation.CacheResult;
import javax.cache.annotation.CacheValue;
import org.springframework.cache.Cache;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.cache.jcache.config.JCacheableService;
import org.springframework.cache.jcache.interceptor.SimpleGeneratedCacheKey;
import org.springframework.cache.jcache.support.TestableCacheKeyGenerator;
import org.springframework.cache.jcache.support.TestableCacheResolverFactory;
@ -111,7 +111,7 @@ public class AnnotatedJCacheableService implements JCacheableService<Long> {
@Override
@CachePut(afterInvocation = false)
public void earlyPut(String id, @CacheValue Object value) {
SimpleGeneratedCacheKey key = new SimpleGeneratedCacheKey(id);
Object key = SimpleKeyGenerator.generateKey(id);
Cache.ValueWrapper valueWrapper = defaultCache.get(key);
if (valueWrapper == null) {
throw new AssertionError("Excepted value to be put in cache with key " + key);
@ -143,7 +143,7 @@ public class AnnotatedJCacheableService implements JCacheableService<Long> {
@Override
@CacheRemove(afterInvocation = false)
public void earlyRemove(String id) {
SimpleGeneratedCacheKey key = new SimpleGeneratedCacheKey(id);
Object key = SimpleKeyGenerator.generateKey(id);
Cache.ValueWrapper valueWrapper = defaultCache.get(key);
if (valueWrapper != null) {
throw new AssertionError("Value with key " + key + " expected to be already remove from cache");

View File

@ -49,18 +49,17 @@ public class AbstractJCacheConfiguration extends AbstractCachingConfiguration<JC
public JCacheOperationSource cacheOperationSource() {
DefaultJCacheOperationSource source = new DefaultJCacheOperationSource();
if (this.cacheManager != null) {
source.setCacheManager(cacheManager);
source.setCacheManager(this.cacheManager);
}
if (keyGenerator != null) {
source.setKeyGenerator(keyGenerator);
if (this.keyGenerator != null) {
source.setKeyGenerator(this.keyGenerator);
}
if (this.cacheResolver != null) {
source.setCacheResolver(cacheResolver);
source.setCacheResolver(this.cacheResolver);
}
if (this.exceptionCacheResolver != null) {
source.setExceptionCacheResolver(exceptionCacheResolver);
source.setExceptionCacheResolver(this.exceptionCacheResolver);
}
return source;
}

View File

@ -28,7 +28,6 @@ import org.springframework.cache.interceptor.AbstractCacheInvoker;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheOperationInvoker;
import org.springframework.cache.jcache.model.BaseCacheOperation;
/**
* A base interceptor for JSR-107 cache annotations.
@ -37,7 +36,7 @@ import org.springframework.cache.jcache.model.BaseCacheOperation;
* @since 4.1
*/
@SuppressWarnings("serial")
public abstract class AbstractCacheInterceptor<O extends BaseCacheOperation<A>, A extends Annotation>
abstract class AbstractCacheInterceptor<O extends AbstractJCacheOperation<A>, A extends Annotation>
extends AbstractCacheInvoker implements Serializable {
protected final Log logger = LogFactory.getLog(getClass());

View File

@ -25,7 +25,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cache.interceptor.MethodCacheKey;
import org.springframework.cache.jcache.model.JCacheOperation;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.util.ClassUtils;
@ -58,7 +57,7 @@ public abstract class AbstractFallbackJCacheOperationSource
return cached;
}
else {
JCacheOperation<?> operation = computeCacheOperations(method, targetClass);
JCacheOperation<?> operation = computeCacheOperation(method, targetClass);
if (operation != null) {
if (logger.isDebugEnabled()) {
logger.debug("Adding cacheable method '" + method.getName()
@ -70,7 +69,7 @@ public abstract class AbstractFallbackJCacheOperationSource
}
}
private JCacheOperation<?> computeCacheOperations(Method method, Class<?> targetClass) {
private JCacheOperation<?> computeCacheOperation(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
@ -32,30 +32,33 @@ import org.springframework.cache.interceptor.KeyGenerator;
* @author Stephane Nicoll
* @since 4.1
*/
public abstract class BaseKeyCacheOperation<A extends Annotation> extends BaseCacheOperation<A> {
abstract class AbstractJCacheKeyOperation<A extends Annotation> extends AbstractJCacheOperation<A> {
private final KeyGenerator keyGenerator;
private final List<CacheParameterDetail> keyParameterDetails;
/**
* Create a new instance.
* @param methodDetails the {@link CacheMethodDetails} related to the cached method
* @param cacheResolver the cache resolver to resolve regular caches
* @param keyGenerator the key generator to compute cache keys
*/
protected BaseKeyCacheOperation(CacheMethodDetails<A> methodDetails,
protected AbstractJCacheKeyOperation(CacheMethodDetails<A> methodDetails,
CacheResolver cacheResolver, KeyGenerator keyGenerator) {
super(methodDetails, cacheResolver);
this.keyGenerator = keyGenerator;
this.keyParameterDetails = initializeKeyParameterDetails(allParameterDetails);
this.keyParameterDetails = initializeKeyParameterDetails(this.allParameterDetails);
}
/**
* Return the {@link KeyGenerator} to use to compute cache keys.
*/
public KeyGenerator getKeyGenerator() {
return keyGenerator;
return this.keyGenerator;
}
/**
@ -72,7 +75,7 @@ public abstract class BaseKeyCacheOperation<A extends Annotation> extends BaseCa
*/
public CacheInvocationParameter[] getKeyParameters(Object... values) {
List<CacheInvocationParameter> result = new ArrayList<CacheInvocationParameter>();
for (CacheParameterDetail keyParameterDetail : keyParameterDetails) {
for (CacheParameterDetail keyParameterDetail : this.keyParameterDetails) {
int parameterPosition = keyParameterDetail.getParameterPosition();
if (parameterPosition >= values.length) {
throw new IllegalStateException("Values mismatch, key parameter at position "
@ -95,7 +98,7 @@ public abstract class BaseKeyCacheOperation<A extends Annotation> extends BaseCa
annotated.add(allParameter);
}
}
return annotated.size() == 0 ? all : annotated;
return (annotated.isEmpty() ? all : annotated);
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@ -40,7 +40,7 @@ import static java.util.Arrays.*;
* @author Stephane Nicoll
* @since 4.1
*/
public abstract class BaseCacheOperation<A extends Annotation> implements JCacheOperation<A> {
abstract class AbstractJCacheOperation<A extends Annotation> implements JCacheOperation<A> {
private final CacheMethodDetails<A> methodDetails;
@ -54,7 +54,7 @@ public abstract class BaseCacheOperation<A extends Annotation> implements JCache
* @param methodDetails the {@link CacheMethodDetails} related to the cached method
* @param cacheResolver the cache resolver to resolve regular caches
*/
protected BaseCacheOperation(CacheMethodDetails<A> methodDetails, CacheResolver cacheResolver) {
protected AbstractJCacheOperation(CacheMethodDetails<A> methodDetails, CacheResolver cacheResolver) {
Assert.notNull(methodDetails, "method details must not be null.");
Assert.notNull(cacheResolver, "cache resolver must not be null.");
this.methodDetails = methodDetails;
@ -159,13 +159,13 @@ public abstract class BaseCacheOperation<A extends Annotation> implements JCache
private final boolean isValue;
public CacheParameterDetail(Method m, int parameterPosition) {
this.rawType = m.getParameterTypes()[parameterPosition];
public CacheParameterDetail(Method method, int parameterPosition) {
this.rawType = method.getParameterTypes()[parameterPosition];
this.annotations = new LinkedHashSet<Annotation>();
boolean foundKeyAnnotation = false;
boolean foundValueAnnotation = false;
for (Annotation annotation : m.getParameterAnnotations()[parameterPosition]) {
annotations.add(annotation);
for (Annotation annotation : method.getParameterAnnotations()[parameterPosition]) {
this.annotations.add(annotation);
if (CacheKey.class.isAssignableFrom(annotation.annotationType())) {
foundKeyAnnotation = true;
}

View File

@ -23,7 +23,6 @@ import javax.cache.annotation.CacheKeyInvocationContext;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.jcache.model.BaseKeyCacheOperation;
/**
* A base interceptor for JSR-107 key-based cache annotations.
@ -32,7 +31,7 @@ import org.springframework.cache.jcache.model.BaseKeyCacheOperation;
* @since 4.1
*/
@SuppressWarnings("serial")
public abstract class AbstractKeyCacheInterceptor<O extends BaseKeyCacheOperation<A>, A extends Annotation>
abstract class AbstractKeyCacheInterceptor<O extends AbstractJCacheKeyOperation<A>, A extends Annotation>
extends AbstractCacheInterceptor<O, A> {
protected AbstractKeyCacheInterceptor(CacheErrorHandler errorHandler) {

View File

@ -32,12 +32,6 @@ import javax.cache.annotation.CacheResult;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.jcache.model.CachePutOperation;
import org.springframework.cache.jcache.model.CacheRemoveAllOperation;
import org.springframework.cache.jcache.model.CacheRemoveOperation;
import org.springframework.cache.jcache.model.CacheResultOperation;
import org.springframework.cache.jcache.model.DefaultCacheMethodDetails;
import org.springframework.cache.jcache.model.JCacheOperation;
import org.springframework.util.StringUtils;
/**
@ -48,8 +42,7 @@ import org.springframework.util.StringUtils;
* @author Stephane Nicoll
* @since 4.1
*/
public abstract class AnnotationCacheOperationSource
extends AbstractFallbackJCacheOperationSource {
public abstract class AnnotationJCacheOperationSource extends AbstractFallbackJCacheOperationSource {
/**
* Locate or create an instance of the specified {@code type}.
@ -236,7 +229,6 @@ public abstract class AnnotationCacheOperationSource
/**
* Generate a default cache name for the specified {@link Method}.
*
* @param method the annotated method
* @return the default cache name, according to JSR-107
*/

View File

@ -23,7 +23,6 @@ import org.springframework.cache.Cache;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheOperationInvoker;
import org.springframework.cache.jcache.model.CachePutOperation;
/**
* Intercept methods annotated with {@link CachePut}.
@ -32,7 +31,7 @@ import org.springframework.cache.jcache.model.CachePutOperation;
* @since 4.1
*/
@SuppressWarnings("serial")
public class CachePutInterceptor extends AbstractKeyCacheInterceptor<CachePutOperation, CachePut> {
class CachePutInterceptor extends AbstractKeyCacheInterceptor<CachePutOperation, CachePut> {
public CachePutInterceptor(CacheErrorHandler errorHandler) {
super(errorHandler);
@ -41,11 +40,12 @@ public class CachePutInterceptor extends AbstractKeyCacheInterceptor<CachePutOpe
@Override
protected Object invoke(CacheOperationInvocationContext<CachePutOperation> context,
CacheOperationInvoker invoker) {
CacheKeyInvocationContext<CachePut> invocationContext = createCacheKeyInvocationContext(context);
CachePutOperation operation = context.getOperation();
final boolean earlyPut = operation.isEarlyPut();
final Object value = invocationContext.getValueParameter().getValue();
boolean earlyPut = operation.isEarlyPut();
Object value = invocationContext.getValueParameter().getValue();
if (earlyPut) {
cacheValue(context, value);
@ -58,12 +58,12 @@ public class CachePutInterceptor extends AbstractKeyCacheInterceptor<CachePutOpe
}
return result;
}
catch (CacheOperationInvoker.ThrowableWrapper t) {
Throwable ex = t.getOriginal();
if (!earlyPut && operation.getExceptionTypeFilter().match(ex.getClass())) {
catch (CacheOperationInvoker.ThrowableWrapper ex) {
Throwable original = ex.getOriginal();
if (!earlyPut && operation.getExceptionTypeFilter().match(original.getClass())) {
cacheValue(context, value);
}
throw t;
throw ex;
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import java.lang.reflect.Method;
import java.util.List;
@ -34,7 +34,7 @@ import org.springframework.util.ExceptionTypeFilter;
* @since 4.1
* @see CachePut
*/
public class CachePutOperation extends BaseKeyCacheOperation<CachePut> {
class CachePutOperation extends AbstractJCacheKeyOperation<CachePut> {
private final ExceptionTypeFilter exceptionTypeFilter;
@ -47,8 +47,8 @@ public class CachePutOperation extends BaseKeyCacheOperation<CachePut> {
super(methodDetails, cacheResolver, keyGenerator);
CachePut ann = methodDetails.getCacheAnnotation();
this.exceptionTypeFilter = createExceptionTypeFilter(ann.cacheFor(), ann.noCacheFor());
this.valueParameterDetail = initializeValueParameterDetail(methodDetails.getMethod(), allParameterDetails);
if (valueParameterDetail == null) {
this.valueParameterDetail = initializeValueParameterDetail(methodDetails.getMethod(), this.allParameterDetails);
if (this.valueParameterDetail == null) {
throw new IllegalArgumentException("No parameter annotated with @CacheValue was found for " +
"" + methodDetails.getMethod());
}

View File

@ -22,7 +22,6 @@ import org.springframework.cache.Cache;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheOperationInvoker;
import org.springframework.cache.jcache.model.CacheRemoveAllOperation;
/**
* Intercept methods annotated with {@link CacheRemoveAll}.
@ -31,7 +30,7 @@ import org.springframework.cache.jcache.model.CacheRemoveAllOperation;
* @since 4.1
*/
@SuppressWarnings("serial")
public class CacheRemoveAllInterceptor
class CacheRemoveAllInterceptor
extends AbstractCacheInterceptor<CacheRemoveAllOperation, CacheRemoveAll> {
protected CacheRemoveAllInterceptor(CacheErrorHandler errorHandler) {
@ -41,9 +40,10 @@ public class CacheRemoveAllInterceptor
@Override
protected Object invoke(CacheOperationInvocationContext<CacheRemoveAllOperation> context,
CacheOperationInvoker invoker) {
CacheRemoveAllOperation operation = context.getOperation();
final boolean earlyRemove = operation.isEarlyRemove();
boolean earlyRemove = operation.isEarlyRemove();
if (earlyRemove) {
removeAll(context);
@ -56,12 +56,12 @@ public class CacheRemoveAllInterceptor
}
return result;
}
catch (CacheOperationInvoker.ThrowableWrapper t) {
Throwable ex = t.getOriginal();
if (!earlyRemove && operation.getExceptionTypeFilter().match(ex.getClass())) {
catch (CacheOperationInvoker.ThrowableWrapper ex) {
Throwable original = ex.getOriginal();
if (!earlyRemove && operation.getExceptionTypeFilter().match(original.getClass())) {
removeAll(context);
}
throw t;
throw ex;
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import javax.cache.annotation.CacheMethodDetails;
import javax.cache.annotation.CacheRemoveAll;
@ -29,7 +29,7 @@ import org.springframework.util.ExceptionTypeFilter;
* @since 4.1
* @see CacheRemoveAll
*/
public class CacheRemoveAllOperation extends BaseCacheOperation<CacheRemoveAll> {
class CacheRemoveAllOperation extends AbstractJCacheOperation<CacheRemoveAll> {
private final ExceptionTypeFilter exceptionTypeFilter;

View File

@ -22,7 +22,6 @@ import org.springframework.cache.Cache;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheOperationInvoker;
import org.springframework.cache.jcache.model.CacheRemoveOperation;
/**
* Intercept methods annotated with {@link CacheRemove}.
@ -31,7 +30,7 @@ import org.springframework.cache.jcache.model.CacheRemoveOperation;
* @since 4.1
*/
@SuppressWarnings("serial")
public class CacheRemoveEntryInterceptor extends AbstractKeyCacheInterceptor<CacheRemoveOperation, CacheRemove> {
class CacheRemoveEntryInterceptor extends AbstractKeyCacheInterceptor<CacheRemoveOperation, CacheRemove> {
protected CacheRemoveEntryInterceptor(CacheErrorHandler errorHandler) {
super(errorHandler);

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import javax.cache.annotation.CacheMethodDetails;
import javax.cache.annotation.CacheRemove;
@ -30,7 +30,7 @@ import org.springframework.util.ExceptionTypeFilter;
* @since 4.1
* @see CacheRemove
*/
public class CacheRemoveOperation extends BaseKeyCacheOperation<CacheRemove> {
class CacheRemoveOperation extends AbstractJCacheKeyOperation<CacheRemove> {
private final ExceptionTypeFilter exceptionTypeFilter;

View File

@ -20,7 +20,7 @@ import org.springframework.util.Assert;
* @author Stephane Nicoll
* @since 4.1
*/
public class CacheResolverAdapter implements CacheResolver {
class CacheResolverAdapter implements CacheResolver {
private final javax.cache.annotation.CacheResolver target;

View File

@ -23,9 +23,8 @@ import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheOperationInvoker;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.jcache.model.CacheResultOperation;
import org.springframework.util.SerializationUtils;
import org.springframework.util.ExceptionTypeFilter;
import org.springframework.util.SerializationUtils;
/**
* Intercept methods annotated with {@link CacheResult}.
@ -34,7 +33,7 @@ import org.springframework.util.ExceptionTypeFilter;
* @since 4.1
*/
@SuppressWarnings("serial")
public class CacheResultInterceptor extends AbstractKeyCacheInterceptor<CacheResultOperation, CacheResult> {
class CacheResultInterceptor extends AbstractKeyCacheInterceptor<CacheResultOperation, CacheResult> {
public CacheResultInterceptor(CacheErrorHandler errorHandler) {
super(errorHandler);
@ -43,9 +42,9 @@ public class CacheResultInterceptor extends AbstractKeyCacheInterceptor<CacheRes
@Override
protected Object invoke(CacheOperationInvocationContext<CacheResultOperation> context,
CacheOperationInvoker invoker) {
CacheResultOperation operation = context.getOperation();
final Object cacheKey = generateKey(context);
CacheResultOperation operation = context.getOperation();
Object cacheKey = generateKey(context);
Cache cache = resolveCache(context);
Cache exceptionCache = resolveExceptionCache(context);

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import javax.cache.annotation.CacheMethodDetails;
import javax.cache.annotation.CacheResult;
@ -31,7 +31,7 @@ import org.springframework.util.StringUtils;
* @since 4.1
* @see CacheResult
*/
public class CacheResultOperation extends BaseKeyCacheOperation<CacheResult> {
class CacheResultOperation extends AbstractJCacheKeyOperation<CacheResult> {
private final ExceptionTypeFilter exceptionTypeFilter;

View File

@ -25,7 +25,6 @@ import javax.cache.annotation.CacheInvocationContext;
import javax.cache.annotation.CacheInvocationParameter;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.jcache.model.JCacheOperation;
/**
* The default {@link CacheOperationInvocationContext} implementation used
@ -35,7 +34,7 @@ import org.springframework.cache.jcache.model.JCacheOperation;
* @author Stephane Nicoll
* @since 4.1
*/
public class DefaultCacheInvocationContext<A extends Annotation>
class DefaultCacheInvocationContext<A extends Annotation>
implements CacheInvocationContext<A>, CacheOperationInvocationContext<JCacheOperation<A>> {
private final JCacheOperation<A> operation;
@ -56,42 +55,42 @@ public class DefaultCacheInvocationContext<A extends Annotation>
@Override
public JCacheOperation<A> getOperation() {
return operation;
return this.operation;
}
@Override
public Method getMethod() {
return operation.getMethod();
return this.operation.getMethod();
}
@Override
public Object[] getArgs() {
return args.clone();
return this.args.clone();
}
@Override
public Set<Annotation> getAnnotations() {
return operation.getAnnotations();
return this.operation.getAnnotations();
}
@Override
public A getCacheAnnotation() {
return operation.getCacheAnnotation();
return this.operation.getCacheAnnotation();
}
@Override
public String getCacheName() {
return operation.getCacheName();
return this.operation.getCacheName();
}
@Override
public Object getTarget() {
return target;
return this.target;
}
@Override
public CacheInvocationParameter[] getAllParameters() {
return allParameters.clone();
return this.allParameters.clone();
}
@Override

View File

@ -21,23 +21,20 @@ import java.lang.annotation.Annotation;
import javax.cache.annotation.CacheInvocationParameter;
import javax.cache.annotation.CacheKeyInvocationContext;
import org.springframework.cache.jcache.model.BaseKeyCacheOperation;
import org.springframework.cache.jcache.model.CachePutOperation;
/**
* The default {@link CacheKeyInvocationContext} implementation.
*
* @author Stephane Nicoll
* @since 4.1
*/
public class DefaultCacheKeyInvocationContext<A extends Annotation>
class DefaultCacheKeyInvocationContext<A extends Annotation>
extends DefaultCacheInvocationContext<A> implements CacheKeyInvocationContext<A> {
private final CacheInvocationParameter[] keyParameters;
private final CacheInvocationParameter valueParameter;
public DefaultCacheKeyInvocationContext(BaseKeyCacheOperation<A> operation,
public DefaultCacheKeyInvocationContext(AbstractJCacheKeyOperation<A> operation,
Object target, Object[] args) {
super(operation, target, args);
this.keyParameters = operation.getKeyParameters(args);

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import static java.util.Arrays.*;
@ -32,7 +32,7 @@ import javax.cache.annotation.CacheMethodDetails;
* @author Stephane Nicoll
* @since 4.1
*/
public class DefaultCacheMethodDetails<A extends Annotation> implements CacheMethodDetails<A> {
class DefaultCacheMethodDetails<A extends Annotation> implements CacheMethodDetails<A> {
private final Method method;
@ -42,8 +42,8 @@ public class DefaultCacheMethodDetails<A extends Annotation> implements CacheMet
private final String cacheName;
public DefaultCacheMethodDetails(Method method, A cacheAnnotation,
String cacheName) {
public DefaultCacheMethodDetails(Method method, A cacheAnnotation, String cacheName) {
this.method = method;
this.annotations = Collections.unmodifiableSet(
new LinkedHashSet<Annotation>(asList(method.getAnnotations())));
@ -51,32 +51,33 @@ public class DefaultCacheMethodDetails<A extends Annotation> implements CacheMet
this.cacheName = cacheName;
}
@Override
public Method getMethod() {
return method;
return this.method;
}
@Override
public Set<Annotation> getAnnotations() {
return annotations;
return this.annotations;
}
@Override
public A getCacheAnnotation() {
return cacheAnnotation;
return this.cacheAnnotation;
}
@Override
public String getCacheName() {
return cacheName;
return this.cacheName;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("details[");
sb.append("method=").append(method);
sb.append(", cacheAnnotation=").append(cacheAnnotation);
sb.append(", cacheName='").append(cacheName).append('\'');
StringBuilder sb = new StringBuilder("CacheMethodDetails[");
sb.append("method=").append(this.method);
sb.append(", cacheAnnotation=").append(this.cacheAnnotation);
sb.append(", cacheName='").append(this.cacheName).append('\'');
sb.append(']');
return sb.toString();
}

View File

@ -25,6 +25,7 @@ import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleCacheResolver;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
@ -37,12 +38,14 @@ import org.springframework.util.Assert;
* @author Stephane Nicoll
* @since 4.1
*/
public class DefaultJCacheOperationSource extends AnnotationCacheOperationSource
public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSource
implements InitializingBean, ApplicationContextAware {
private CacheManager cacheManager;
private KeyGenerator keyGenerator;
private KeyGenerator keyGenerator = new SimpleKeyGenerator();
private KeyGenerator adaptedKeyGenerator;
private CacheResolver cacheResolver;
@ -50,23 +53,6 @@ public class DefaultJCacheOperationSource extends AnnotationCacheOperationSource
private ApplicationContext applicationContext;
@Override
public void afterPropertiesSet() {
Assert.state((cacheResolver != null && exceptionCacheResolver != null)
|| cacheManager != null, "'cacheManager' is required if cache resolvers are not set.");
Assert.state(this.applicationContext != null, "The application context was not injected as it should.");
if (keyGenerator == null) {
keyGenerator = new KeyGeneratorAdapter(this, new SimpleCacheKeyGenerator());
}
if (cacheResolver == null) {
cacheResolver = new SimpleCacheResolver(cacheManager);
}
if (exceptionCacheResolver == null) {
exceptionCacheResolver = new SimpleExceptionCacheResolver(cacheManager);
}
}
/**
* Set the default {@link CacheManager} to use to lookup cache by name. Only mandatory
* if the {@linkplain CacheResolver cache resolvers} have not been set.
@ -76,13 +62,18 @@ public class DefaultJCacheOperationSource extends AnnotationCacheOperationSource
}
/**
* Set the default {@link KeyGenerator}. If none is set, a default JSR-107 compliant
* key generator is used.
* Set the default {@link KeyGenerator}. If none is set, a {@link SimpleKeyGenerator}
* honoringKe the JSR-107 {@link javax.cache.annotation.CacheKey} and
* {@link javax.cache.annotation.CacheValue} will be used.
*/
public void setKeyGenerator(KeyGenerator keyGenerator) {
this.keyGenerator = keyGenerator;
}
public KeyGenerator getKeyGenerator() {
return this.keyGenerator;
}
/**
* Set the {@link CacheResolver} to resolve regular caches. If none is set, a default
* implementation using the specified cache manager will be used.
@ -91,6 +82,10 @@ public class DefaultJCacheOperationSource extends AnnotationCacheOperationSource
this.cacheResolver = cacheResolver;
}
public CacheResolver getCacheResolver() {
return this.cacheResolver;
}
/**
* Set the {@link CacheResolver} to resolve exception caches. If none is set, a default
* implementation using the specified cache manager will be used.
@ -99,14 +94,33 @@ public class DefaultJCacheOperationSource extends AnnotationCacheOperationSource
this.exceptionCacheResolver = exceptionCacheResolver;
}
public CacheResolver getExceptionCacheResolver() {
return this.exceptionCacheResolver;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void afterPropertiesSet() {
Assert.state((this.cacheResolver != null && this.exceptionCacheResolver != null)
|| this.cacheManager != null, "'cacheManager' is required if cache resolvers are not set.");
Assert.state(this.applicationContext != null, "The application context was not injected as it should.");
this.adaptedKeyGenerator = new KeyGeneratorAdapter(this, this.keyGenerator);
if (this.cacheResolver == null) {
this.cacheResolver = new SimpleCacheResolver(this.cacheManager);
}
if (this.exceptionCacheResolver == null) {
this.exceptionCacheResolver = new SimpleExceptionCacheResolver(this.cacheManager);
}
}
@Override
protected <T> T getBean(Class<T> type) {
Map<String, T> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, type);
Map<String, T> map = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, type);
if (map.size() == 1) {
return map.values().iterator().next();
}
@ -116,18 +130,18 @@ public class DefaultJCacheOperationSource extends AnnotationCacheOperationSource
}
@Override
public CacheResolver getDefaultCacheResolver() {
return cacheResolver;
protected CacheResolver getDefaultCacheResolver() {
return this.cacheResolver;
}
@Override
public CacheResolver getDefaultExceptionCacheResolver() {
return exceptionCacheResolver;
protected CacheResolver getDefaultExceptionCacheResolver() {
return this.exceptionCacheResolver;
}
@Override
public KeyGenerator getDefaultKeyGenerator() {
return keyGenerator;
protected KeyGenerator getDefaultKeyGenerator() {
return this.adaptedKeyGenerator;
}
}

View File

@ -25,14 +25,9 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cache.interceptor.AbstractCacheInvoker;
import org.springframework.cache.interceptor.BasicCacheOperation;
import org.springframework.cache.interceptor.BasicOperation;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheOperationInvoker;
import org.springframework.cache.jcache.model.CachePutOperation;
import org.springframework.cache.jcache.model.CacheRemoveAllOperation;
import org.springframework.cache.jcache.model.CacheRemoveOperation;
import org.springframework.cache.jcache.model.CacheResultOperation;
import org.springframework.cache.jcache.model.JCacheOperation;
import org.springframework.util.Assert;
/**
@ -134,7 +129,7 @@ public class JCacheAspectSupport extends AbstractCacheInvoker implements Initial
CacheOperationInvoker adapter = new CacheOperationInvokerAdapter(invoker);
BasicCacheOperation operation = context.getOperation();
BasicOperation operation = context.getOperation();
if (operation instanceof CacheResultOperation) {
return cacheResultInterceptor.invoke(
(CacheOperationInvocationContext<CacheResultOperation>) context, adapter);

View File

@ -35,11 +35,11 @@ import org.springframework.cache.interceptor.CacheOperationInvoker;
* <p>JCacheInterceptors are thread-safe.
*
* @author Stephane Nicoll
* @since 4.1
* @see org.springframework.cache.interceptor.CacheInterceptor
*/
@SuppressWarnings("serial")
public class JCacheInterceptor extends JCacheAspectSupport
implements MethodInterceptor, Serializable {
public class JCacheInterceptor extends JCacheAspectSupport implements MethodInterceptor, Serializable {
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {

View File

@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import java.lang.annotation.Annotation;
import javax.cache.annotation.CacheInvocationParameter;
import javax.cache.annotation.CacheMethodDetails;
import org.springframework.cache.interceptor.BasicCacheOperation;
import org.springframework.cache.interceptor.BasicOperation;
import org.springframework.cache.interceptor.CacheResolver;
/**
@ -33,8 +33,7 @@ import org.springframework.cache.interceptor.CacheResolver;
* @author Stephane Nicoll
* @since 4.1
*/
public interface JCacheOperation<A extends Annotation>
extends CacheMethodDetails<A>, BasicCacheOperation {
public interface JCacheOperation<A extends Annotation> extends BasicOperation, CacheMethodDetails<A> {
/**
* Return the {@link CacheResolver} instance to use to resolve the cache to

View File

@ -18,8 +18,6 @@ package org.springframework.cache.jcache.interceptor;
import java.lang.reflect.Method;
import org.springframework.cache.jcache.model.JCacheOperation;
/**
* Interface used by {@link JCacheInterceptor}. Implementations know how to source
* cache operation attributes from standard JSR-107 annotations.

View File

@ -2,58 +2,103 @@ package org.springframework.cache.jcache.interceptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.cache.annotation.CacheInvocationParameter;
import javax.cache.annotation.CacheKeyGenerator;
import javax.cache.annotation.CacheKeyInvocationContext;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.jcache.model.BaseKeyCacheOperation;
import org.springframework.cache.jcache.model.JCacheOperation;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/**
* Spring's {@link KeyGenerator} implementation that delegates to a standard
* JSR-107 {@link javax.cache.annotation.CacheKeyGenerator}.
* <p>Used internally to invoke user-based JSR-107 cache key generators.
* Spring's {@link KeyGenerator} implementation that either delegates to a
* standard JSR-107 {@link javax.cache.annotation.CacheKeyGenerator}, or
* wrap a standard {@link KeyGenerator} so that only relevant parameters
* are handled.
*
* @author Stephane Nicoll
* @since 4.1
*/
public class KeyGeneratorAdapter implements KeyGenerator {
class KeyGeneratorAdapter implements KeyGenerator {
private final JCacheOperationSource cacheOperationSource;
private final CacheKeyGenerator target;
private KeyGenerator keyGenerator;
public KeyGeneratorAdapter(JCacheOperationSource cacheOperationSource, CacheKeyGenerator target) {
Assert.notNull(cacheOperationSource, "cacheOperationSource must be set.");
Assert.notNull(target, "cache key generator must be set.");
private CacheKeyGenerator cacheKeyGenerator;
/**
* Create an instance with the given {@link KeyGenerator} so that {@link javax.cache.annotation.CacheKey}
* and {@link javax.cache.annotation.CacheValue} are handled according to the spec.
*/
public KeyGeneratorAdapter(JCacheOperationSource cacheOperationSource, KeyGenerator target) {
Assert.notNull(cacheOperationSource, "cacheOperationSource must not be null.");
Assert.notNull(target, "KeyGenerator must not be null");
this.cacheOperationSource = cacheOperationSource;
this.target = target;
this.keyGenerator = target;
}
/**
* Return the underlying {@link CacheKeyGenerator} that this instance is using.
* Create an instance used to wrap the specified {@link javax.cache.annotation.CacheKeyGenerator}.
*/
protected CacheKeyGenerator getTarget() {
return target;
public KeyGeneratorAdapter(JCacheOperationSource cacheOperationSource, CacheKeyGenerator target) {
Assert.notNull(cacheOperationSource, "cacheOperationSource must not be null.");
Assert.notNull(target, "KeyGenerator must not be null");
this.cacheOperationSource = cacheOperationSource;
this.cacheKeyGenerator = target;
}
/**
* Return the target key generator to use in the form of either a {@link KeyGenerator}
* or a {@link CacheKeyGenerator}.
*/
public Object getTarget() {
return (this.keyGenerator != null ? this.keyGenerator : this.cacheKeyGenerator);
}
@Override
public Object generate(Object target, Method method, Object... params) {
JCacheOperation<?> operation = cacheOperationSource.getCacheOperation(method, target.getClass());
if (!(BaseKeyCacheOperation.class.isInstance(operation))) {
JCacheOperation<?> operation = this.cacheOperationSource.getCacheOperation(method, target.getClass());
if (!(AbstractJCacheKeyOperation.class.isInstance(operation))) {
throw new IllegalStateException("Invalid operation, should be a key-based operation " + operation);
}
CacheKeyInvocationContext<?> invocationContext = createCacheKeyInvocationContext(target, operation, params);
return this.target.generateCacheKey(invocationContext);
if (this.cacheKeyGenerator != null) {
return this.cacheKeyGenerator.generateCacheKey(invocationContext);
}
else {
return doGenerate(this.keyGenerator, invocationContext);
}
}
@SuppressWarnings("unchecked")
private static Object doGenerate(KeyGenerator keyGenerator, CacheKeyInvocationContext<?> context) {
List<Object> parameters = new ArrayList<Object>();
for (CacheInvocationParameter param : context.getKeyParameters()) {
Object value = param.getValue();
if (param.getParameterPosition() == context.getAllParameters().length - 1 &&
context.getMethod().isVarArgs()) {
parameters.addAll((List<Object>) CollectionUtils.arrayToList(value));
}
else {
parameters.add(value);
}
}
return keyGenerator.generate(context.getTarget(), context.getMethod(),
parameters.toArray(new Object[parameters.size()]));
}
@SuppressWarnings("unchecked")
private CacheKeyInvocationContext<?> createCacheKeyInvocationContext(Object target,
JCacheOperation<?> operation, Object[] params) {
BaseKeyCacheOperation<Annotation> keyCacheOperation = (BaseKeyCacheOperation<Annotation>) operation;
AbstractJCacheKeyOperation<Annotation> keyCacheOperation = (AbstractJCacheKeyOperation<Annotation>) operation;
return new DefaultCacheKeyInvocationContext<Annotation>(keyCacheOperation, target, params);
}

View File

@ -1,47 +0,0 @@
/*
* 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.jcache.interceptor;
import java.lang.annotation.Annotation;
import javax.cache.annotation.CacheInvocationParameter;
import javax.cache.annotation.CacheKeyGenerator;
import javax.cache.annotation.CacheKeyInvocationContext;
import javax.cache.annotation.GeneratedCacheKey;
/**
* A JSR-107 compliant key generator. Uses only the parameters that have been annotated
* with {@link javax.cache.annotation.CacheKey} or all of them if none are set, except
* the {@link javax.cache.annotation.CacheValue} one.
*
* @author Stephane Nicoll
* @since 4.1
* @see javax.cache.annotation.CacheKeyInvocationContext#getKeyParameters()
*/
public class SimpleCacheKeyGenerator implements CacheKeyGenerator {
@Override
public GeneratedCacheKey generateCacheKey(CacheKeyInvocationContext<? extends Annotation> context) {
CacheInvocationParameter[] keyParameters = context.getKeyParameters();
final Object[] parameters = new Object[keyParameters.length];
for (int i = 0; i < keyParameters.length; i++) {
parameters[i] = keyParameters[i].getValue();
}
return new SimpleGeneratedCacheKey(parameters);
}
}

View File

@ -20,11 +20,10 @@ import java.util.Collection;
import java.util.Collections;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.BaseCacheResolver;
import org.springframework.cache.interceptor.BasicCacheOperation;
import org.springframework.cache.interceptor.AbstractCacheResolver;
import org.springframework.cache.interceptor.BasicOperation;
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.jcache.model.CacheResultOperation;
/**
* A simple {@link CacheResolver} that resolves the exception cache
@ -33,9 +32,9 @@ import org.springframework.cache.jcache.model.CacheResultOperation;
*
* @author Stephane Nicoll
* @since 4.1
* @see org.springframework.cache.jcache.model.CacheResultOperation#getExceptionCacheName()
* @see CacheResultOperation#getExceptionCacheName()
*/
public class SimpleExceptionCacheResolver extends BaseCacheResolver {
public class SimpleExceptionCacheResolver extends AbstractCacheResolver {
public SimpleExceptionCacheResolver(CacheManager cacheManager) {
super(cacheManager);
@ -43,7 +42,7 @@ public class SimpleExceptionCacheResolver extends BaseCacheResolver {
@Override
protected Collection<String> getCacheNames(CacheOperationInvocationContext<?> context) {
BasicCacheOperation operation = context.getOperation();
BasicOperation operation = context.getOperation();
if (!(operation instanceof CacheResultOperation)) {
throw new IllegalStateException("Could not extract exception cache name from " + operation);
}

View File

@ -1,20 +0,0 @@
package org.springframework.cache.jcache.interceptor;
import javax.cache.annotation.GeneratedCacheKey;
import org.springframework.cache.interceptor.SimpleKey;
/**
* A {@link SimpleKey} that implements the {@link GeneratedCacheKey} contract
* required by JSR-107
*
* @author Stephane Nicoll
*/
@SuppressWarnings("serial")
public final class SimpleGeneratedCacheKey extends SimpleKey implements GeneratedCacheKey {
public SimpleGeneratedCacheKey(Object... elements) {
super(elements);
}
}

View File

@ -1,5 +0,0 @@
/**
* Resolved model of JSR-107 cache annotations. Used internally by the interceptors
* in org.springframework.cache.jcache.interceptor.
*/
package org.springframework.cache.jcache.model;

View File

@ -28,7 +28,7 @@ import org.junit.rules.TestName;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.jcache.interceptor.SimpleGeneratedCacheKey;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.context.ApplicationContext;
/**
@ -523,7 +523,7 @@ public abstract class AbstractJCacheAnnotationTests {
private Object createKey(Object... params) {
return new SimpleGeneratedCacheKey(params);
return SimpleKeyGenerator.generateKey(params);
}
private Cache getCache(String name) {

View File

@ -61,11 +61,11 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(FullCachingConfig.class);
DefaultJCacheOperationSource cos = context.getBean(DefaultJCacheOperationSource.class);
assertSame(context.getBean(KeyGenerator.class), cos.getDefaultKeyGenerator());
assertSame(context.getBean(KeyGenerator.class), cos.getKeyGenerator());
assertSame(context.getBean("cacheResolver", CacheResolver.class),
cos.getDefaultCacheResolver());
cos.getCacheResolver());
assertSame(context.getBean("exceptionCacheResolver", CacheResolver.class),
cos.getDefaultExceptionCacheResolver());
cos.getExceptionCacheResolver());
JCacheInterceptor interceptor = context.getBean(JCacheInterceptor.class);
assertSame(context.getBean("errorHandler", CacheErrorHandler.class), interceptor.getErrorHandler());
}
@ -76,14 +76,14 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
new AnnotationConfigApplicationContext(EmptyConfigSupportConfig.class);
DefaultJCacheOperationSource cos = context.getBean(DefaultJCacheOperationSource.class);
assertNotNull(cos.getDefaultCacheResolver());
assertEquals(SimpleCacheResolver.class, cos.getDefaultCacheResolver().getClass());
assertNotNull(cos.getCacheResolver());
assertEquals(SimpleCacheResolver.class, cos.getCacheResolver().getClass());
assertSame(context.getBean(CacheManager.class),
((SimpleCacheResolver) cos.getDefaultCacheResolver()).getCacheManager());
assertNotNull(cos.getDefaultExceptionCacheResolver());
assertEquals(SimpleExceptionCacheResolver.class, cos.getDefaultExceptionCacheResolver().getClass());
((SimpleCacheResolver) cos.getCacheResolver()).getCacheManager());
assertNotNull(cos.getExceptionCacheResolver());
assertEquals(SimpleExceptionCacheResolver.class, cos.getExceptionCacheResolver().getClass());
assertSame(context.getBean(CacheManager.class),
((SimpleExceptionCacheResolver) cos.getDefaultExceptionCacheResolver()).getCacheManager());
((SimpleExceptionCacheResolver) cos.getExceptionCacheResolver()).getCacheManager());
context.close();
}
@ -93,9 +93,9 @@ public class JCacheJavaConfigTests extends AbstractJCacheAnnotationTests {
new AnnotationConfigApplicationContext(FullCachingConfigSupport.class);
DefaultJCacheOperationSource cos = context.getBean(DefaultJCacheOperationSource.class);
assertSame(context.getBean("cacheResolver"), cos.getDefaultCacheResolver());
assertSame(context.getBean("keyGenerator"), cos.getDefaultKeyGenerator());
assertSame(context.getBean("exceptionCacheResolver"), cos.getDefaultExceptionCacheResolver());
assertSame(context.getBean("cacheResolver"), cos.getCacheResolver());
assertSame(context.getBean("keyGenerator"), cos.getKeyGenerator());
assertSame(context.getBean("exceptionCacheResolver"), cos.getExceptionCacheResolver());
context.close();
}

View File

@ -44,7 +44,7 @@ public class JCacheNamespaceDrivenTests extends AbstractJCacheAnnotationTests {
"/org/springframework/cache/jcache/config/jCacheNamespaceDriven-resolver.xml");
DefaultJCacheOperationSource ci = context.getBean(DefaultJCacheOperationSource.class);
assertSame(context.getBean("cacheResolver"), ci.getDefaultCacheResolver());
assertSame(context.getBean("cacheResolver"), ci.getCacheResolver());
context.close();
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import static org.junit.Assert.*;

View File

@ -29,6 +29,7 @@ import javax.cache.annotation.CacheResult;
import javax.cache.annotation.CacheValue;
import org.springframework.cache.Cache;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.cache.jcache.config.JCacheableService;
import org.springframework.cache.jcache.support.TestableCacheKeyGenerator;
import org.springframework.cache.jcache.support.TestableCacheResolverFactory;
@ -109,7 +110,7 @@ public class AnnotatedJCacheableService implements JCacheableService<Long> {
@Override
@CachePut(afterInvocation = false)
public void earlyPut(String id, @CacheValue Object value) {
SimpleGeneratedCacheKey key = new SimpleGeneratedCacheKey(id);
Object key = SimpleKeyGenerator.generateKey(id);
Cache.ValueWrapper valueWrapper = defaultCache.get(key);
if (valueWrapper == null) {
throw new AssertionError("Excepted value to be put in cache with key " + key);
@ -141,7 +142,7 @@ public class AnnotatedJCacheableService implements JCacheableService<Long> {
@Override
@CacheRemove(afterInvocation = false)
public void earlyRemove(String id) {
SimpleGeneratedCacheKey key = new SimpleGeneratedCacheKey(id);
Object key = SimpleKeyGenerator.generateKey(id);
Cache.ValueWrapper valueWrapper = defaultCache.get(key);
if (valueWrapper != null) {
throw new AssertionError("Value with key " + key + " expected to be already remove from cache");

View File

@ -34,12 +34,6 @@ import org.junit.Test;
import org.springframework.cache.interceptor.CacheResolver;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.jcache.AbstractJCacheTests;
import org.springframework.cache.jcache.model.BaseKeyCacheOperation;
import org.springframework.cache.jcache.model.CachePutOperation;
import org.springframework.cache.jcache.model.CacheRemoveAllOperation;
import org.springframework.cache.jcache.model.CacheRemoveOperation;
import org.springframework.cache.jcache.model.CacheResultOperation;
import org.springframework.cache.jcache.model.JCacheOperation;
import org.springframework.cache.jcache.support.TestableCacheKeyGenerator;
import org.springframework.cache.jcache.support.TestableCacheResolver;
import org.springframework.cache.jcache.support.TestableCacheResolverFactory;
@ -142,7 +136,8 @@ public class AnnotationCacheOperationSourceTests extends AbstractJCacheTests {
getCacheOperation(CacheResultOperation.class, CustomService.class, name.getMethodName(), Long.class);
assertJCacheResolver(operation.getCacheResolver(), TestableCacheResolver.class);
assertJCacheResolver(operation.getExceptionCacheResolver(), null);
assertEquals(defaultKeyGenerator, operation.getKeyGenerator());
assertEquals(KeyGeneratorAdapter.class, operation.getKeyGenerator().getClass());
assertEquals(defaultKeyGenerator, ((KeyGeneratorAdapter) operation.getKeyGenerator()).getTarget());
}
@Test
@ -184,9 +179,10 @@ public class AnnotationCacheOperationSourceTests extends AbstractJCacheTests {
assertCacheKeyGenerator(operation.getKeyGenerator(), TestableCacheKeyGenerator.class);
}
private void assertDefaults(BaseKeyCacheOperation<?> operation) {
private void assertDefaults(AbstractJCacheKeyOperation<?> operation) {
assertEquals(defaultCacheResolver, operation.getCacheResolver());
assertEquals(defaultKeyGenerator, operation.getKeyGenerator());
assertEquals(KeyGeneratorAdapter.class, operation.getKeyGenerator().getClass());
assertEquals(defaultKeyGenerator, ((KeyGeneratorAdapter) operation.getKeyGenerator()).getTarget());
}
protected <T extends JCacheOperation<?>> T getDefaultCacheOperation(Class<T> operationType, Class<?>... parameterTypes) {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import static org.junit.Assert.*;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import static org.junit.Assert.*;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import static org.junit.Assert.*;

View File

@ -34,8 +34,6 @@ import org.junit.rules.ExpectedException;
import org.springframework.cache.Cache;
import org.springframework.cache.jcache.AbstractJCacheTests;
import org.springframework.cache.jcache.model.CacheResultOperation;
import org.springframework.cache.jcache.model.DefaultCacheMethodDetails;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import static org.junit.Assert.*;

View File

@ -40,6 +40,7 @@ import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.cache.jcache.config.JCacheConfigurerSupport;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -72,7 +73,7 @@ public class JCacheErrorHandlerTests {
@Test
public void getFail() {
UnsupportedOperationException exception = new UnsupportedOperationException("Test exception on get");
SimpleGeneratedCacheKey key = new SimpleGeneratedCacheKey(0L);
Object key = SimpleKeyGenerator.generateKey(0L);
doThrow(exception).when(cache).get(key);
this.simpleService.get(0L);
@ -82,7 +83,7 @@ public class JCacheErrorHandlerTests {
@Test
public void putFail() {
UnsupportedOperationException exception = new UnsupportedOperationException("Test exception on put");
SimpleGeneratedCacheKey key = new SimpleGeneratedCacheKey(0L);
Object key = SimpleKeyGenerator.generateKey(0L);
doThrow(exception).when(cache).put(key, 234L);
this.simpleService.put(0L, 234L);
@ -92,7 +93,7 @@ public class JCacheErrorHandlerTests {
@Test
public void evictFail() {
UnsupportedOperationException exception = new UnsupportedOperationException("Test exception on evict");
SimpleGeneratedCacheKey key = new SimpleGeneratedCacheKey(0L);
Object key = SimpleKeyGenerator.generateKey(0L);
doThrow(exception).when(cache).evict(key);
this.simpleService.evict(0L);

View File

@ -0,0 +1,159 @@
/*
* 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.jcache.interceptor;
import static org.junit.Assert.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong;
import javax.cache.annotation.CacheDefaults;
import javax.cache.annotation.CacheKey;
import javax.cache.annotation.CacheResult;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.interceptor.SimpleKey;
import org.springframework.cache.interceptor.SimpleKeyGenerator;
import org.springframework.cache.jcache.config.JCacheConfigurerSupport;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
* @author Stephane Nicoll
*/
public class JCacheKeyGeneratorTests {
private TestKeyGenerator keyGenerator;
private SimpleService simpleService;
private Cache cache;
@Before
public void setup() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
this.keyGenerator = context.getBean(TestKeyGenerator.class);
this.simpleService = context.getBean(SimpleService.class);
this.cache = context.getBean(CacheManager.class).getCache("test");
}
@Test
public void getSimple() {
this.keyGenerator.expect(1L);
Object first = this.simpleService.get(1L);
Object second = this.simpleService.get(1L);
assertSame(first, second);
Object key = new SimpleKey(1L);
assertEquals(first, cache.get(key).get());
}
@Test
public void getFlattenVararg() {
this.keyGenerator.expect(1L, "foo", "bar");
Object first = this.simpleService.get(1L, "foo", "bar");
Object second = this.simpleService.get(1L, "foo", "bar");
assertSame(first, second);
Object key = new SimpleKey(1L, "foo", "bar");
assertEquals(first, cache.get(key).get());
}
@Test
public void getFiltered() {
this.keyGenerator.expect(1L);
Object first = this.simpleService.getFiltered(1L, "foo", "bar");
Object second = this.simpleService.getFiltered(1L, "foo", "bar");
assertSame(first, second);
Object key = new SimpleKey(1L);
assertEquals(first, cache.get(key).get());
}
@Configuration
@EnableCaching
static class Config extends JCacheConfigurerSupport {
@Bean
@Override
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
@Bean
@Override
public KeyGenerator keyGenerator() {
return new TestKeyGenerator();
}
@Bean
public SimpleService simpleService() {
return new SimpleService();
}
}
@CacheDefaults(cacheName = "test")
public static class SimpleService {
private AtomicLong counter = new AtomicLong();
@CacheResult
public Object get(long id) {
return counter.getAndIncrement();
}
@CacheResult
public Object get(long id, String... items) {
return counter.getAndIncrement();
}
@CacheResult
public Object getFiltered(@CacheKey long id, String... items) {
return counter.getAndIncrement();
}
}
private static class TestKeyGenerator extends SimpleKeyGenerator {
private Object[] expectedParams;
private void expect(Object... params) {
this.expectedParams = params;
}
@Override
public Object generate(Object target, Method method, Object... params) {
assertTrue("Unexpected parameters: expected: "
+ Arrays.toString(this.expectedParams) + " but got: " + Arrays.toString(params),
Arrays.equals(expectedParams, params));
return new SimpleKey(params);
}
}
}

View File

@ -1,4 +1,4 @@
package org.springframework.cache.jcache.model;
package org.springframework.cache.jcache.interceptor;
import javax.cache.annotation.CacheKey;
import javax.cache.annotation.CachePut;

View File

@ -6,7 +6,7 @@ import javax.cache.annotation.CacheKeyGenerator;
import javax.cache.annotation.CacheKeyInvocationContext;
import javax.cache.annotation.GeneratedCacheKey;
import org.springframework.cache.jcache.interceptor.SimpleGeneratedCacheKey;
import org.springframework.cache.interceptor.SimpleKey;
/**
* A simple test key generator that only takes the first key arguments into
@ -22,4 +22,13 @@ public class TestableCacheKeyGenerator implements CacheKeyGenerator {
return new SimpleGeneratedCacheKey(context.getKeyParameters()[0]);
}
private static class SimpleGeneratedCacheKey extends SimpleKey implements GeneratedCacheKey {
public SimpleGeneratedCacheKey(Object... elements) {
super(elements);
}
}
}

View File

@ -33,16 +33,18 @@ import org.springframework.util.Assert;
* @author Stephane Nicoll
* @since 4.1
*/
public abstract class BaseCacheResolver implements CacheResolver, InitializingBean {
public abstract class AbstractCacheResolver implements CacheResolver, InitializingBean {
private CacheManager cacheManager;
protected BaseCacheResolver(CacheManager cacheManager) {
protected AbstractCacheResolver() {
}
protected AbstractCacheResolver(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
protected BaseCacheResolver() {
}
/**
* Set the {@link CacheManager} that this instance should use.
@ -55,14 +57,15 @@ public abstract class BaseCacheResolver implements CacheResolver, InitializingBe
* Return the {@link CacheManager} that this instance use.
*/
public CacheManager getCacheManager() {
return cacheManager;
return this.cacheManager;
}
@Override
public void afterPropertiesSet() {
Assert.notNull(cacheManager, "CacheManager must not be null");
Assert.notNull(this.cacheManager, "CacheManager must not be null");
}
@Override
public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) {
Collection<String> cacheNames = getCacheNames(context);
@ -72,8 +75,11 @@ public abstract class BaseCacheResolver implements CacheResolver, InitializingBe
else {
Collection<Cache> result = new ArrayList<Cache>();
for (String cacheName : cacheNames) {
Cache cache = cacheManager.getCache(cacheName);
Assert.notNull(cache, "Cannot find cache named '" + cacheName + "' for " + context.getOperation());
Cache cache = this.cacheManager.getCache(cacheName);
if (cache == null) {
throw new IllegalArgumentException("Cannot find cache named '" +
cacheName + "' for " + context.getOperation());
}
result.add(cache);
}
return result;
@ -84,7 +90,6 @@ public abstract class BaseCacheResolver implements CacheResolver, InitializingBe
* Provide the name of the cache(s) to resolve against the current cache manager.
* <p>It is acceptable to return {@code null} to indicate that no cache could
* be resolved for this invocation.
*
* @param context the context of the particular invocation
* @return the cache name(s) to resolve or {@code null} if no cache should be resolved
*/

View File

@ -24,7 +24,7 @@ import java.util.Set;
* @author Stephane Nicoll
* @since 4.1
*/
public interface BasicCacheOperation {
public interface BasicOperation {
/**
* Return the cache name(s) associated to the operation.

View File

@ -29,7 +29,7 @@ import org.springframework.util.Assert;
* @author Stephane Nicoll
* @since 3.1
*/
public abstract class CacheOperation implements BasicCacheOperation {
public abstract class CacheOperation implements BasicOperation {
private Set<String> cacheNames = Collections.emptySet();

View File

@ -27,7 +27,7 @@ import java.lang.reflect.Method;
* @author Stephane Nicoll
* @since 4.1
*/
public interface CacheOperationInvocationContext<O extends BasicCacheOperation> {
public interface CacheOperationInvocationContext<O extends BasicOperation> {
/**
* Return the cache operation

View File

@ -30,7 +30,7 @@ import org.springframework.cache.CacheManager;
* @author Stephane Nicoll
* @since 4.1
*/
public class NamedCacheResolver extends BaseCacheResolver {
public class NamedCacheResolver extends AbstractCacheResolver {
private Collection<String> cacheNames;

View File

@ -24,13 +24,13 @@ import org.springframework.cache.CacheManager;
/**
* A simple {@link CacheResolver} that resolves the {@link Cache} instance(s)
* based on a configurable {@link CacheManager} and the name of the
* cache(s) as provided by {@link BasicCacheOperation#getCacheNames() getCacheNames()}
* cache(s) as provided by {@link BasicOperation#getCacheNames() getCacheNames()}
*
* @author Stephane Nicoll
* @since 4.1
* @see BasicCacheOperation#getCacheNames()
* @see BasicOperation#getCacheNames()
*/
public class SimpleCacheResolver extends BaseCacheResolver {
public class SimpleCacheResolver extends AbstractCacheResolver {
public SimpleCacheResolver() {
}

View File

@ -39,6 +39,13 @@ public class SimpleKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return generateKey(params);
}
/**
* Generate a key based on the specified parameters.
*/
public static Object generateKey(Object... params) {
if (params.length == 0) {
return SimpleKey.EMPTY;
}

View File

@ -250,7 +250,7 @@ public class CacheResolverCustomisationTests {
* runtime (i.e. based on method invocation parameters).
* <p>Expects the second argument to hold the name of the cache to use
*/
private static class RuntimeCacheResolver extends BaseCacheResolver {
private static class RuntimeCacheResolver extends AbstractCacheResolver {
private RuntimeCacheResolver(CacheManager cacheManager) {
super(cacheManager);
@ -263,7 +263,7 @@ public class CacheResolverCustomisationTests {
}
}
private static class NullCacheResolver extends BaseCacheResolver {
private static class NullCacheResolver extends AbstractCacheResolver {
private NullCacheResolver(CacheManager cacheManager) {
super(cacheManager);