提交 f75d4e13 编写于 作者: P Phillip Webb

Polish cache abstraction code

Polish cache abstraction code and refactor CacheAspectSupport.
上级 b122ca68
......@@ -42,14 +42,18 @@ import org.springframework.util.CollectionUtils;
public abstract class AbstractCachingConfiguration implements ImportAware {
protected AnnotationAttributes enableCaching;
protected CacheManager cacheManager;
protected KeyGenerator keyGenerator;
@Autowired(required=false)
private Collection<CacheManager> cacheManagerBeans;
@Autowired(required=false)
private Collection<CachingConfigurer> cachingConfigurers;
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableCaching = AnnotationAttributes.fromMap(
......@@ -59,6 +63,7 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
importMetadata.getClassName());
}
/**
* Determine which {@code CacheManager} bean to use. Prefer the result of
* {@link CachingConfigurer#cacheManager()} over any by-type matching. If none, fall
......
......@@ -48,69 +48,17 @@ import org.w3c.dom.Element;
*/
class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
/**
* Simple, reusable class used for overriding defaults.
*
* @author Costin Leau
*/
private static class Props {
private String key;
private String condition;
private String method;
private String[] caches = null;
Props(Element root) {
String defaultCache = root.getAttribute("cache");
key = root.getAttribute("key");
condition = root.getAttribute("condition");
method = root.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(defaultCache)) {
caches = StringUtils.commaDelimitedListToStringArray(defaultCache.trim());
}
}
<T extends CacheOperation> T merge(Element element, ReaderContext readerCtx, T op) {
String cache = element.getAttribute("cache");
// sanity check
String[] localCaches = caches;
if (StringUtils.hasText(cache)) {
localCaches = StringUtils.commaDelimitedListToStringArray(cache.trim());
} else {
if (caches == null) {
readerCtx.error("No cache specified specified for " + element.getNodeName(), element);
}
}
op.setCacheNames(localCaches);
op.setKey(getAttributeValue(element, "key", this.key));
op.setCondition(getAttributeValue(element, "condition", this.condition));
return op;
}
String merge(Element element, ReaderContext readerCtx) {
String m = element.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(m)) {
return m.trim();
}
if (StringUtils.hasText(method)) {
return method;
}
readerCtx.error("No method specified for " + element.getNodeName(), element);
return null;
}
}
private static final String CACHEABLE_ELEMENT = "cacheable";
private static final String CACHE_EVICT_ELEMENT = "cache-evict";
private static final String CACHE_PUT_ELEMENT = "cache-put";
private static final String METHOD_ATTRIBUTE = "method";
private static final String DEFS_ELEMENT = "caching";
@Override
protected Class<?> getBeanClass(Element element) {
return CacheInterceptor.class;
......@@ -226,4 +174,66 @@ class CacheAdviceParser extends AbstractSingleBeanDefinitionParser {
return defaultValue;
}
/**
* Simple, reusable class used for overriding defaults.
*
* @author Costin Leau
*/
private static class Props {
private String key;
private String condition;
private String method;
private String[] caches = null;
Props(Element root) {
String defaultCache = root.getAttribute("cache");
key = root.getAttribute("key");
condition = root.getAttribute("condition");
method = root.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(defaultCache)) {
caches = StringUtils.commaDelimitedListToStringArray(defaultCache.trim());
}
}
<T extends CacheOperation> T merge(Element element, ReaderContext readerCtx, T op) {
String cache = element.getAttribute("cache");
// sanity check
String[] localCaches = caches;
if (StringUtils.hasText(cache)) {
localCaches = StringUtils.commaDelimitedListToStringArray(cache.trim());
} else {
if (caches == null) {
readerCtx.error("No cache specified specified for " + element.getNodeName(), element);
}
}
op.setCacheNames(localCaches);
op.setKey(getAttributeValue(element, "key", this.key));
op.setCondition(getAttributeValue(element, "condition", this.condition));
return op;
}
String merge(Element element, ReaderContext readerCtx) {
String m = element.getAttribute(METHOD_ATTRIBUTE);
if (StringUtils.hasText(m)) {
return m.trim();
}
if (StringUtils.hasText(method)) {
return method;
}
readerCtx.error("No method specified for " + element.getNodeName(), element);
return null;
}
}
}
......@@ -35,6 +35,7 @@ import org.w3c.dom.Element;
public class CacheNamespaceHandler extends NamespaceHandlerSupport {
static final String CACHE_MANAGER_ATTRIBUTE = "cache-manager";
static final String DEFAULT_CACHE_MANAGER_BEAN_NAME = "cacheManager";
static String extractCacheManager(Element element) {
......
......@@ -25,6 +25,7 @@ package org.springframework.cache.interceptor;
public class CacheEvictOperation extends CacheOperation {
private boolean cacheWide = false;
private boolean beforeInvocation = false;
......
......@@ -41,14 +41,6 @@ import org.aopalliance.intercept.MethodInvocation;
@SuppressWarnings("serial")
public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {
private static class ThrowableWrapper extends RuntimeException {
private final Throwable original;
ThrowableWrapper(Throwable original) {
this.original = original;
}
}
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
......@@ -70,4 +62,14 @@ public class CacheInterceptor extends CacheAspectSupport implements MethodInterc
throw th.original;
}
}
private static class ThrowableWrapper extends RuntimeException {
private final Throwable original;
ThrowableWrapper(Throwable original) {
this.original = original;
}
}
}
......@@ -23,15 +23,18 @@ import java.util.Set;
import org.springframework.util.Assert;
/**
* Base class implementing {@link CacheOperation}.
* Base class for cache operations.
*
* @author Costin Leau
*/
public abstract class CacheOperation {
private Set<String> cacheNames = Collections.emptySet();
private String condition = "";
private String key = "";
private String name = "";
......
......@@ -42,8 +42,10 @@ import org.springframework.aop.support.DefaultPointcutAdvisor;
public class CacheProxyFactoryBean extends AbstractSingletonProxyFactoryBean {
private final CacheInterceptor cachingInterceptor = new CacheInterceptor();
private Pointcut pointcut;
/**
* Set a pointcut, i.e a bean that can cause conditional invocation
* of the CacheInterceptor depending on method and attributes passed.
......@@ -58,12 +60,11 @@ public class CacheProxyFactoryBean extends AbstractSingletonProxyFactoryBean {
@Override
protected Object createMainInterceptor() {
this.cachingInterceptor.afterPropertiesSet();
if (this.pointcut != null) {
return new DefaultPointcutAdvisor(this.pointcut, this.cachingInterceptor);
} else {
if (this.pointcut == null) {
// Rely on default pointcut.
throw new UnsupportedOperationException();
}
return new DefaultPointcutAdvisor(this.pointcut, this.cachingInterceptor);
}
/**
......
......@@ -35,6 +35,7 @@ public class CompositeCacheOperationSource implements CacheOperationSource, Seri
private final CacheOperationSource[] cacheOperationSources;
/**
* Create a new CompositeCacheOperationSource for the given sources.
* @param cacheOperationSources the CacheOperationSource instances to combine
......
......@@ -42,8 +42,10 @@ import org.springframework.cache.interceptor.KeyGenerator;
public class DefaultKeyGenerator implements KeyGenerator {
public static final int NO_PARAM_KEY = 0;
public static final int NULL_PARAM_KEY = 53;
@Override
public Object generate(Object target, Method method, Object... params) {
if (params.length == 1) {
......
......@@ -42,6 +42,7 @@ class ExpressionEvaluator {
public static final Object NO_RESULT = new Object();
private final SpelExpressionParser parser = new SpelExpressionParser();
// shared param discoverer since it caches data internally
......
......@@ -85,14 +85,14 @@ class LazyParamAwareEvaluationContext extends StandardEvaluationContext {
return;
}
String mKey = toString(this.method);
Method targetMethod = this.methodCache.get(mKey);
String methodKey = toString(this.method);
Method targetMethod = this.methodCache.get(methodKey);
if (targetMethod == null) {
targetMethod = AopUtils.getMostSpecificMethod(this.method, this.targetClass);
if (targetMethod == null) {
targetMethod = this.method;
}
this.methodCache.put(mKey, targetMethod);
this.methodCache.put(methodKey, targetMethod);
}
// save arguments as indexed variables
......
......@@ -42,9 +42,11 @@ public class NameMatchCacheOperationSource implements CacheOperationSource, Seri
*/
protected static final Log logger = LogFactory.getLog(NameMatchCacheOperationSource.class);
/** Keys are method names; values are TransactionAttributes */
private Map<String, Collection<CacheOperation>> nameMap = new LinkedHashMap<String, Collection<CacheOperation>>();
/**
* Set a name/attribute map, consisting of method names
* (e.g. "myMethod") and CacheOperation instances
......
......@@ -31,6 +31,7 @@ public class SimpleCacheManager extends AbstractCacheManager {
private Collection<? extends Cache> caches;
/**
* Specify the collection of Cache instances to use for this CacheManager.
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册