Browse Source
+ add missing files (remember to check "show unversioned files") git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4316 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/merge
10 changed files with 809 additions and 0 deletions
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.annotation; |
||||
|
||||
import java.io.Serializable; |
||||
import java.lang.reflect.AnnotatedElement; |
||||
import java.lang.reflect.Method; |
||||
import java.util.Collections; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.cache.interceptor.AbstractFallbackCacheOperationSource; |
||||
import org.springframework.cache.interceptor.CacheOperation; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* |
||||
* Implementation of the {@link org.springframework.cache.interceptor.CacheOperationSource} |
||||
* interface for working with caching metadata in JDK 1.5+ annotation format. |
||||
* |
||||
* <p>This class reads Spring's JDK 1.5+ {@link Cacheable} and {@link CacheEvict} |
||||
* annotations and exposes corresponding caching operation definition to Spring's cache infrastructure. |
||||
* This class may also serve as base class for a custom CacheOperationSource. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements |
||||
Serializable { |
||||
|
||||
private final boolean publicMethodsOnly; |
||||
|
||||
private final Set<CacheAnnotationParser> annotationParsers; |
||||
|
||||
/** |
||||
* Create a default AnnotationCacheOperationSource, supporting |
||||
* public methods that carry the <code>Cacheable</code> and <code>CacheEvict</code> |
||||
* annotations. |
||||
*/ |
||||
public AnnotationCacheOperationSource() { |
||||
this(true); |
||||
} |
||||
|
||||
/** |
||||
* Create a custom AnnotationCacheOperationSource, supporting |
||||
* public methods that carry the <code>Cacheable</code> and |
||||
* <code>CacheEvict</code> annotations. |
||||
* |
||||
* @param publicMethodsOnly whether to support only annotated public methods |
||||
* typically for use with proxy-based AOP), or protected/private methods as well |
||||
* (typically used with AspectJ class weaving) |
||||
*/ |
||||
public AnnotationCacheOperationSource(boolean publicMethodsOnly) { |
||||
this.publicMethodsOnly = publicMethodsOnly; |
||||
this.annotationParsers = new LinkedHashSet<CacheAnnotationParser>(1); |
||||
this.annotationParsers.add(new SpringCachingAnnotationParser()); |
||||
} |
||||
|
||||
/** |
||||
* Create a custom AnnotationCacheOperationSource. |
||||
* @param annotationParsers the CacheAnnotationParser to use |
||||
*/ |
||||
public AnnotationCacheOperationSource(CacheAnnotationParser... annotationParsers) { |
||||
this.publicMethodsOnly = true; |
||||
Assert.notEmpty(annotationParsers, "At least one CacheAnnotationParser needs to be specified"); |
||||
Set<CacheAnnotationParser> parsers = new LinkedHashSet<CacheAnnotationParser>(annotationParsers.length); |
||||
Collections.addAll(parsers, annotationParsers); |
||||
this.annotationParsers = parsers; |
||||
} |
||||
|
||||
@Override |
||||
protected CacheOperation findCacheOperation(Class<?> clazz) { |
||||
return determineCacheOperation(clazz); |
||||
} |
||||
|
||||
@Override |
||||
protected CacheOperation findCacheOperation(Method method) { |
||||
return determineCacheOperation(method); |
||||
} |
||||
|
||||
/** |
||||
* Determine the cache operation definition for the given method or class. |
||||
* <p>This implementation delegates to configured |
||||
* {@link CacheAnnotationParser CacheAnnotationParsers} |
||||
* for parsing known annotations into Spring's metadata attribute class. |
||||
* Returns <code>null</code> if it's not cacheable. |
||||
* <p>Can be overridden to support custom annotations that carry caching metadata. |
||||
* @param ae the annotated method or class
|
||||
* @return CacheOperation the configured caching operation, |
||||
* or <code>null</code> if none was found |
||||
*/ |
||||
protected CacheOperation determineCacheOperation(AnnotatedElement ae) { |
||||
for (CacheAnnotationParser annotationParser : this.annotationParsers) { |
||||
CacheOperation attr = annotationParser.parseCacheAnnotation(ae); |
||||
if (attr != null) { |
||||
return attr; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* By default, only public methods can be made cacheable. |
||||
*/ |
||||
@Override |
||||
protected boolean allowPublicMethodsOnly() { |
||||
return this.publicMethodsOnly; |
||||
} |
||||
} |
||||
@ -0,0 +1,218 @@
@@ -0,0 +1,218 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.lang.reflect.Modifier; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.core.BridgeMethodResolver; |
||||
import org.springframework.util.ClassUtils; |
||||
import org.springframework.util.ObjectUtils; |
||||
|
||||
/** |
||||
* Abstract implementation of {@link CacheOperation} that caches |
||||
* attributes for methods and implements a fallback policy: 1. specific target |
||||
* method; 2. target class; 3. declaring method; 4. declaring class/interface. |
||||
* |
||||
* <p>Defaults to using the target class's caching attribute if none is |
||||
* associated with the target method. Any caching attribute associated with |
||||
* the target method completely overrides a class caching attribute. |
||||
* If none found on the target class, the interface that the invoked method |
||||
* has been called through (in case of a JDK proxy) will be checked. |
||||
* |
||||
* <p>This implementation caches attributes by method after they are first used. |
||||
* If it is ever desirable to allow dynamic changing of cacheable attributes |
||||
* (which is very unlikely), caching could be made configurable. |
||||
|
||||
* @author Costin Leau |
||||
* @see org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource |
||||
*/ |
||||
public abstract class AbstractFallbackCacheOperationSource implements CacheOperationSource { |
||||
|
||||
/** |
||||
* Canonical value held in cache to indicate no caching attribute was |
||||
* found for this method and we don't need to look again. |
||||
*/ |
||||
private final static CacheOperation NULL_CACHING_ATTRIBUTE = new CacheUpdateOperation(); |
||||
|
||||
/** |
||||
* Logger available to subclasses. |
||||
* <p>As this base class is not marked Serializable, the logger will be recreated |
||||
* after serialization - provided that the concrete subclass is Serializable. |
||||
*/ |
||||
protected final Log logger = LogFactory.getLog(getClass()); |
||||
|
||||
/** |
||||
* Cache of CacheOperationDefinitions, keyed by DefaultCacheKey (Method + target Class). |
||||
* <p>As this base class is not marked Serializable, the cache will be recreated |
||||
* after serialization - provided that the concrete subclass is Serializable. |
||||
*/ |
||||
final Map<Object, CacheOperation> attributeCache = new ConcurrentHashMap<Object, CacheOperation>(); |
||||
|
||||
/** |
||||
* Determine the caching attribute for this method invocation. |
||||
* <p>Defaults to the class's caching attribute if no method attribute is found. |
||||
* @param method the method for the current invocation (never <code>null</code>) |
||||
* @param targetClass the target class for this invocation (may be <code>null</code>) |
||||
* @return {@link CacheOperation} for this method, or <code>null</code> if the method |
||||
* is not cacheable |
||||
*/ |
||||
public CacheOperation getCacheOperation(Method method, Class<?> targetClass) { |
||||
// First, see if we have a cached value.
|
||||
Object cacheKey = getCacheKey(method, targetClass); |
||||
CacheOperation cached = this.attributeCache.get(cacheKey); |
||||
if (cached != null) { |
||||
if (cached == NULL_CACHING_ATTRIBUTE) { |
||||
return null; |
||||
} |
||||
// Value will either be canonical value indicating there is no caching attribute,
|
||||
// or an actual caching attribute.
|
||||
return cached; |
||||
} |
||||
else { |
||||
// We need to work it out.
|
||||
CacheOperation cacheDef = computeCacheOperationDefinition(method, targetClass); |
||||
// Put it in the cache.
|
||||
if (cacheDef == null) { |
||||
this.attributeCache.put(cacheKey, NULL_CACHING_ATTRIBUTE); |
||||
} |
||||
else { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Adding cacheable method '" + method.getName() + "' with attribute: " + cacheDef); |
||||
} |
||||
this.attributeCache.put(cacheKey, cacheDef); |
||||
} |
||||
return cacheDef; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Determine a cache key for the given method and target class. |
||||
* <p>Must not produce same key for overloaded methods. |
||||
* Must produce same key for different instances of the same method. |
||||
* @param method the method (never <code>null</code>) |
||||
* @param targetClass the target class (may be <code>null</code>) |
||||
* @return the cache key (never <code>null</code>) |
||||
*/ |
||||
protected Object getCacheKey(Method method, Class<?> targetClass) { |
||||
return new DefaultCacheKey(method, targetClass); |
||||
} |
||||
|
||||
/** |
||||
* Same signature as {@link #getTransactionAttribute}, but doesn't cache the result. |
||||
* {@link #getTransactionAttribute} is effectively a caching decorator for this method. |
||||
* @see #getTransactionAttribute |
||||
*/ |
||||
private CacheOperation computeCacheOperationDefinition(Method method, Class<?> targetClass) { |
||||
// Don't allow no-public methods as required.
|
||||
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { |
||||
return null; |
||||
} |
||||
|
||||
// The method may be on an interface, but we need attributes from the target class.
|
||||
// If the target class is null, the method will be unchanged.
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass); |
||||
// If we are dealing with method with generic parameters, find the original method.
|
||||
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); |
||||
|
||||
// First try is the method in the target class.
|
||||
CacheOperation opDef = findCacheOperation(specificMethod); |
||||
if (opDef != null) { |
||||
return opDef; |
||||
} |
||||
|
||||
// Second try is the caching operation on the target class.
|
||||
opDef = findCacheOperation(specificMethod.getDeclaringClass()); |
||||
if (opDef != null) { |
||||
return opDef; |
||||
} |
||||
|
||||
if (specificMethod != method) { |
||||
// Fall back is to look at the original method.
|
||||
opDef = findCacheOperation(method); |
||||
if (opDef != null) { |
||||
return opDef; |
||||
} |
||||
// Last fall back is the class of the original method.
|
||||
return findCacheOperation(method.getDeclaringClass()); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Subclasses need to implement this to return the caching attribute |
||||
* for the given method, if any. |
||||
* @param method the method to retrieve the attribute for |
||||
* @return all caching attribute associated with this method |
||||
* (or <code>null</code> if none) |
||||
*/ |
||||
protected abstract CacheOperation findCacheOperation(Method method); |
||||
|
||||
/** |
||||
* Subclasses need to implement this to return the caching attribute |
||||
* for the given class, if any. |
||||
* @param clazz the class to retrieve the attribute for |
||||
* @return all caching attribute associated with this class
|
||||
* (or <code>null</code> if none) |
||||
*/ |
||||
protected abstract CacheOperation findCacheOperation(Class<?> clazz); |
||||
|
||||
/** |
||||
* Should only public methods be allowed to have caching semantics? |
||||
* <p>The default implementation returns <code>false</code>. |
||||
*/ |
||||
protected boolean allowPublicMethodsOnly() { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Default cache key for the CacheOperationDefinition cache. |
||||
*/ |
||||
private static class DefaultCacheKey { |
||||
|
||||
private final Method method; |
||||
|
||||
private final Class<?> targetClass; |
||||
|
||||
public DefaultCacheKey(Method method, Class<?> targetClass) { |
||||
this.method = method; |
||||
this.targetClass = targetClass; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object other) { |
||||
if (this == other) { |
||||
return true; |
||||
} |
||||
if (!(other instanceof DefaultCacheKey)) { |
||||
return false; |
||||
} |
||||
DefaultCacheKey otherKey = (DefaultCacheKey) other; |
||||
return (this.method.equals(otherKey.method) && ObjectUtils.nullSafeEquals(this.targetClass, |
||||
otherKey.targetClass)); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return this.method.hashCode() * 29 + (this.targetClass != null ? this.targetClass.hashCode() : 0); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
import org.springframework.aop.ClassFilter; |
||||
import org.springframework.aop.Pointcut; |
||||
import org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor; |
||||
|
||||
/** |
||||
* Advisor driven by a {@link CacheOperationSource}, used to include a |
||||
* cache advice bean for methods that are cacheable. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { |
||||
|
||||
private CacheOperationSource cacheDefinitionSource; |
||||
|
||||
private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() { |
||||
@Override |
||||
protected CacheOperationSource getCacheOperationSource() { |
||||
return cacheDefinitionSource; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* Set the cache operation attribute source which is used to find cache |
||||
* attributes. This should usually be identical to the source reference |
||||
* set on the cache interceptor itself. |
||||
* @see CacheInterceptor#setCacheAttributeSource |
||||
*/ |
||||
public void setCacheDefinitionSource(CacheOperationSource cacheDefinitionSource) { |
||||
this.cacheDefinitionSource = cacheDefinitionSource; |
||||
} |
||||
|
||||
/** |
||||
* Set the {@link ClassFilter} to use for this pointcut. |
||||
* Default is {@link ClassFilter#TRUE}. |
||||
*/ |
||||
public void setClassFilter(ClassFilter classFilter) { |
||||
this.pointcut.setClassFilter(classFilter); |
||||
} |
||||
|
||||
public Pointcut getPointcut() { |
||||
return this.pointcut; |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
/** |
||||
* Class describing an 'evict' operation. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
public class CacheEvictOperation extends CacheOperation { |
||||
|
||||
private boolean cacheWide = false; |
||||
|
||||
public boolean isCacheWide() { |
||||
return cacheWide; |
||||
} |
||||
|
||||
public void setCacheWide(boolean cacheWide) { |
||||
this.cacheWide = cacheWide; |
||||
} |
||||
|
||||
@Override |
||||
protected StringBuilder getOperationDescription() { |
||||
StringBuilder sb = super.getOperationDescription(); |
||||
sb.append(","); |
||||
sb.append(cacheWide); |
||||
return sb; |
||||
} |
||||
} |
||||
@ -0,0 +1,128 @@
@@ -0,0 +1,128 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Base class implementing {@link CacheOperation}. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
public abstract class CacheOperation { |
||||
|
||||
private Set<String> cacheNames = Collections.emptySet(); |
||||
private String condition = ""; |
||||
private String key = ""; |
||||
private String name = ""; |
||||
|
||||
|
||||
public Set<String> getCacheNames() { |
||||
return cacheNames; |
||||
} |
||||
|
||||
public String getCondition() { |
||||
return condition; |
||||
} |
||||
|
||||
public String getKey() { |
||||
return key; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
|
||||
public void setCacheName(String cacheName) { |
||||
Assert.hasText(cacheName); |
||||
this.cacheNames = Collections.singleton(cacheName); |
||||
} |
||||
|
||||
public void setCacheNames(String[] cacheNames) { |
||||
Assert.notEmpty(cacheNames); |
||||
this.cacheNames = new LinkedHashSet<String>(cacheNames.length); |
||||
for (String string : cacheNames) { |
||||
this.cacheNames.add(string); |
||||
} |
||||
} |
||||
|
||||
public void setCondition(String condition) { |
||||
Assert.notNull(condition); |
||||
this.condition = condition; |
||||
} |
||||
|
||||
public void setKey(String key) { |
||||
Assert.notNull(key); |
||||
this.key = key; |
||||
} |
||||
|
||||
public void setName(String name) { |
||||
Assert.hasText(name); |
||||
this.name = name; |
||||
} |
||||
|
||||
/** |
||||
* This implementation compares the <code>toString()</code> results. |
||||
* @see #toString() |
||||
*/ |
||||
@Override |
||||
public boolean equals(Object other) { |
||||
return (other instanceof CacheOperation && toString().equals(other.toString())); |
||||
} |
||||
|
||||
/** |
||||
* This implementation returns <code>toString()</code>'s hash code. |
||||
* @see #toString() |
||||
*/ |
||||
@Override |
||||
public int hashCode() { |
||||
return toString().hashCode(); |
||||
} |
||||
|
||||
/** |
||||
* Return an identifying description for this cache operation. |
||||
* <p>Has to be overridden in subclasses for correct <code>equals</code> |
||||
* and <code>hashCode</code> behavior. Alternatively, {@link #equals} |
||||
* and {@link #hashCode} can be overridden themselves. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return getOperationDescription().toString(); |
||||
} |
||||
|
||||
/** |
||||
* Return an identifying description for this caching operation. |
||||
* <p>Available to subclasses, for inclusion in their <code>toString()</code> result. |
||||
*/ |
||||
protected StringBuilder getOperationDescription() { |
||||
StringBuilder result = new StringBuilder(); |
||||
result.append("CacheDefinition["); |
||||
result.append(name); |
||||
result.append("] caches="); |
||||
result.append(cacheNames); |
||||
result.append(" | condition='"); |
||||
result.append(condition); |
||||
result.append("' | key='"); |
||||
result.append(key); |
||||
result.append("'"); |
||||
return result; |
||||
} |
||||
} |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
import java.lang.reflect.Method; |
||||
|
||||
|
||||
/** |
||||
* Interface used by CacheInterceptor. Implementations know |
||||
* how to source cache operation attributes, whether from configuration, |
||||
* metadata attributes at source level, or anywhere else. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
public interface CacheOperationSource { |
||||
|
||||
/** |
||||
* Return the cache operation definition for this method. |
||||
* Return null if the method is not cacheable. |
||||
* @param method method |
||||
* @param targetClass target class. May be <code>null</code>, in which |
||||
* case the declaring class of the method must be used. |
||||
* @return {@link CacheOperation} the matching cache operation, |
||||
* or <code>null</code> if none found |
||||
*/ |
||||
CacheOperation getCacheOperation(Method method, Class<?> targetClass); |
||||
} |
||||
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
import java.io.Serializable; |
||||
import java.lang.reflect.Method; |
||||
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcut; |
||||
import org.springframework.util.ObjectUtils; |
||||
|
||||
/** |
||||
* Inner class that implements a Pointcut that matches if the underlying |
||||
* {@link CacheOperationSource} has an attribute for a given method. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
abstract class CacheOperationSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { |
||||
|
||||
public boolean matches(Method method, Class<?> targetClass) { |
||||
CacheOperationSource cas = getCacheOperationSource(); |
||||
return (cas == null || cas.getCacheOperation(method, targetClass) != null); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object other) { |
||||
if (this == other) { |
||||
return true; |
||||
} |
||||
if (!(other instanceof CacheOperationSourcePointcut)) { |
||||
return false; |
||||
} |
||||
CacheOperationSourcePointcut otherPc = (CacheOperationSourcePointcut) other; |
||||
return ObjectUtils.nullSafeEquals(getCacheOperationSource(), |
||||
otherPc.getCacheOperationSource()); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return CacheOperationSourcePointcut.class.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return getClass().getName() + ": " + getCacheOperationSource(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Obtain the underlying CacheOperationDefinitionSource (may be <code>null</code>). |
||||
* To be implemented by subclasses. |
||||
*/ |
||||
protected abstract CacheOperationSource getCacheOperationSource(); |
||||
} |
||||
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
/** |
||||
* Class describing an 'update' operation. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
public class CacheUpdateOperation extends CacheOperation { |
||||
|
||||
} |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
/* |
||||
* Copyright 2010-2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
import java.io.Serializable; |
||||
import java.lang.reflect.Method; |
||||
|
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Composite {@link CacheOperationSource} implementation that iterates |
||||
* over a given array of {@link CacheOperationSource} instances. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
@SuppressWarnings("serial") |
||||
public class CompositeCacheOperationSource implements CacheOperationSource, Serializable { |
||||
|
||||
private final CacheOperationSource[] cacheDefinitionSources; |
||||
|
||||
/** |
||||
* Create a new CompositeCachingDefinitionSource for the given sources. |
||||
* @param cacheDefinitionSourcess the CacheDefinitionSource instances to combine |
||||
*/ |
||||
public CompositeCacheOperationSource(CacheOperationSource[] cacheDefinitionSources) { |
||||
Assert.notNull(cacheDefinitionSources, "cacheDefinitionSource array must not be null"); |
||||
this.cacheDefinitionSources = cacheDefinitionSources; |
||||
} |
||||
|
||||
/** |
||||
* Return the CacheDefinitionSource instances that this |
||||
* CompositeCachingDefinitionSource combines. |
||||
*/ |
||||
public final CacheOperationSource[] getCacheDefinitionSources() { |
||||
return this.cacheDefinitionSources; |
||||
} |
||||
|
||||
|
||||
public CacheOperation getCacheOperation(Method method, Class<?> targetClass) { |
||||
for (CacheOperationSource source : cacheDefinitionSources) { |
||||
CacheOperation definition = source.getCacheOperation(method, targetClass); |
||||
if (definition != null) { |
||||
return definition; |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
||||
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
/* |
||||
* Copyright 2011 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.interceptor; |
||||
|
||||
import org.springframework.cache.Cache.ValueWrapper; |
||||
|
||||
/** |
||||
* Default implementation for {@link org.springframework.cache.Cache.ValueWrapper}. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
public class DefaultValue<V> implements ValueWrapper<V> { |
||||
|
||||
private final V value; |
||||
|
||||
public DefaultValue(V value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
public V get() { |
||||
return value; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue