From 6ec0405287cd0e786a094b1da5b1d4c55a67e304 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 22 Jul 2011 09:32:56 +0000 Subject: [PATCH] general revision of cache package; added ConcurrentMapCacheManager git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4760 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../java/org/springframework/cache/Cache.java | 70 ++++--- .../springframework/cache/CacheManager.java | 21 +-- .../AnnotationCacheOperationSource.java | 25 +-- .../annotation/CacheAnnotationParser.java | 4 +- .../cache/annotation/CacheEvict.java | 19 +- .../cache/annotation/Cacheable.java | 12 +- .../SpringCacheAnnotationParser.java | 68 +++++++ .../SpringCachingAnnotationParser.java | 84 --------- .../cache/concurrent/ConcurrentMapCache.java | 125 ++++++++----- .../ConcurrentMapCacheFactoryBean.java | 77 +++++--- .../concurrent/ConcurrentMapCacheManager.java | 101 ++++++++++ ...tationDrivenCacheBeanDefinitionParser.java | 17 +- .../cache/config/CacheNamespaceHandler.java | 4 +- .../cache/ehcache/EhCacheCache.java | 36 ++-- .../cache/ehcache/EhCacheCacheManager.java | 54 +++--- .../AbstractFallbackCacheOperationSource.java | 14 +- ...eanFactoryCacheOperationSourceAdvisor.java | 15 +- .../cache/interceptor/CacheAspectSupport.java | 173 ++++++++++-------- .../interceptor/CacheEvictOperation.java | 17 +- .../CacheExpressionRootObject.java | 101 +++++----- .../cache/interceptor/CacheInterceptor.java | 21 ++- .../cache/interceptor/CacheOperation.java | 10 +- .../interceptor/CacheOperationSource.java | 17 +- .../CacheOperationSourcePointcut.java | 10 +- .../interceptor/CacheProxyFactoryBean.java | 4 +- .../interceptor/CacheUpdateOperation.java | 7 +- .../CompositeCacheOperationSource.java | 32 ++-- .../DefaultCacheExpressionRootObject.java | 74 -------- .../DefaultKeyGenerator.java | 19 +- .../interceptor/ExpressionEvaluator.java | 46 ++--- .../cache/{ => interceptor}/KeyGenerator.java | 8 +- .../LazyParamAwareEvaluationContext.java | 48 ++--- .../cache/support/AbstractCacheManager.java | 65 +++---- .../cache/support/CompositeCacheManager.java | 62 ++++--- .../cache/support/NoOpCacheManager.java | 9 +- .../cache/support/SimpleCacheManager.java | 21 ++- ...alueWrapper.java => ValueWrapperImpl.java} | 14 +- ...erTest.java => NoOpCacheManagerTests.java} | 2 +- ...cheTest.java => ConcurrentCacheTests.java} | 6 +- .../ConcurrentMapCacheManagerTests.java | 63 +++++++ ...Test.java => AbstractAnnotationTests.java} | 2 +- ...va => AnnotationNamespaceDrivenTests.java} | 2 +- ...notationTest.java => AnnotationTests.java} | 2 +- ...eCacheTest.java => EhCacheCacheTests.java} | 4 +- ...est.java => AbstractNativeCacheTests.java} | 2 +- .../config/annotationDrivenCacheConfig.xml | 4 +- 46 files changed, 898 insertions(+), 693 deletions(-) create mode 100644 org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java delete mode 100644 org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCachingAnnotationParser.java create mode 100644 org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java delete mode 100644 org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java rename org.springframework.context/src/main/java/org/springframework/cache/{support => interceptor}/DefaultKeyGenerator.java (75%) rename org.springframework.context/src/main/java/org/springframework/cache/{ => interceptor}/KeyGenerator.java (84%) rename org.springframework.context/src/main/java/org/springframework/cache/support/{DefaultValueWrapper.java => ValueWrapperImpl.java} (70%) rename org.springframework.context/src/test/java/org/springframework/cache/{NoOpCacheManagerTest.java => NoOpCacheManagerTests.java} (94%) rename org.springframework.context/src/test/java/org/springframework/cache/concurrent/{ConcurrentCacheTest.java => ConcurrentCacheTests.java} (79%) create mode 100644 org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java rename org.springframework.context/src/test/java/org/springframework/cache/config/{AbstractAnnotationTest.java => AbstractAnnotationTests.java} (95%) rename org.springframework.context/src/test/java/org/springframework/cache/config/{AnnotationNamespaceDrivenTest.java => AnnotationNamespaceDrivenTests.java} (88%) rename org.springframework.context/src/test/java/org/springframework/cache/config/{AnnotationTest.java => AnnotationTests.java} (89%) rename org.springframework.context/src/test/java/org/springframework/cache/ehcache/{EhCacheCacheTest.java => EhCacheCacheTests.java} (88%) rename org.springframework.context/src/test/java/org/springframework/cache/vendor/{AbstractNativeCacheTest.java => AbstractNativeCacheTests.java} (93%) diff --git a/org.springframework.context/src/main/java/org/springframework/cache/Cache.java b/org.springframework.context/src/main/java/org/springframework/cache/Cache.java index b37030dbf0a..b31afda05fe 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/Cache.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/Cache.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -16,73 +16,67 @@ package org.springframework.cache; - /** * Interface that defines the common cache operations. - * + * * Note: Due to the generic use of caching, it is recommended that * implementations allow storage of null values (for example to - * cache methods that return null). - * + * cache methods that return null). + * * @author Costin Leau + * @since 3.1 */ public interface Cache { /** - * A (wrapper) object representing a cache value. - */ - interface ValueWrapper { - /** - * Returns the actual value in the cache. - * - * @return cache value - */ - Object get(); - } - - /** - * Returns the cache name. - * - * @return the cache name. + * Return the cache name. */ String getName(); /** - * Returns the the native, underlying cache provider. - * - * @return the underlying native cache provider. + * Return the the underlying native cache provider. */ Object getNativeCache(); /** - * Returns the value to which this cache maps the specified key. Returns - * null if the cache contains no mapping for this key. - * + * Return the value to which this cache maps the specified key. Returns + * null if the cache contains no mapping for this key. * @param key key whose associated value is to be returned. - * @return the value to which this cache maps the specified key, or - * null if the cache contains no mapping for this key. + * @return the value to which this cache maps the specified key, + * or null if the cache contains no mapping for this key */ ValueWrapper get(Object key); /** - * Associates the specified value with the specified key in this cache. - * If the cache previously contained a mapping for this key, the old + * Associate the specified value with the specified key in this cache. + *

If the cache previously contained a mapping for this key, the old * value is replaced by the specified value. - * - * @param key key with which the specified value is to be associated. - * @param value value to be associated with the specified key. + * @param key the key with which the specified value is to be associated + * @param value the value to be associated with the specified key */ void put(Object key, Object value); /** - * Evicts the mapping for this key from this cache if it is present. - * - * @param key key whose mapping is to be removed from the cache. + * Evict the mapping for this key from this cache if it is present. + * @param key the key whose mapping is to be removed from the cache */ void evict(Object key); /** - * Removes all mappings from the cache. + * Remove all mappings from the cache. */ void clear(); -} \ No newline at end of file + + + /** + * A (wrapper) object representing a cache value. + */ + interface ValueWrapper { + + /** + * Return the actual value in the cache. + */ + Object get(); + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/CacheManager.java b/org.springframework.context/src/main/java/org/springframework/cache/CacheManager.java index 268e9c3a409..186f188cdf7 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/CacheManager.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/CacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -18,26 +18,25 @@ package org.springframework.cache; import java.util.Collection; - /** - * Entity managing {@link Cache}s. - * + * A manager for a set of {@link Cache}s. + * * @author Costin Leau + * @since 3.1 */ public interface CacheManager { /** - * Returns the cache associated with the given name. - * - * @param name cache identifier - cannot be null - * @return associated cache or null if none is found + * Return the cache associated with the given name. + * @param name cache identifier (must not be null) + * @return associated cache, or null if none is found */ Cache getCache(String name); /** - * Returns a collection of the caches known by this cache manager. - * - * @return names of caches known by the cache manager. + * Return a collection of the caches known by this cache manager. + * @return names of caches known by the cache manager. */ Collection getCacheNames(); + } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/annotation/AnnotationCacheOperationSource.java b/org.springframework.context/src/main/java/org/springframework/cache/annotation/AnnotationCacheOperationSource.java index a8ef94fbd31..05f9d8a3620 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/annotation/AnnotationCacheOperationSource.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/annotation/AnnotationCacheOperationSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -37,29 +37,28 @@ import org.springframework.util.Assert; * This class may also serve as base class for a custom CacheOperationSource. * * @author Costin Leau + * @since 3.1 */ @SuppressWarnings("serial") -public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements - Serializable { +public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource + implements Serializable { private final boolean publicMethodsOnly; private final Set annotationParsers; + /** - * Create a default AnnotationCacheOperationSource, supporting - * public methods that carry the Cacheable and CacheEvict - * annotations. + * Create a default AnnotationCacheOperationSource, supporting public methods + * that carry the Cacheable and CacheEvict annotations. */ public AnnotationCacheOperationSource() { this(true); } /** - * Create a custom AnnotationCacheOperationSource, supporting - * public methods that carry the Cacheable and - * CacheEvict annotations. - * + * Create a default AnnotationCacheOperationSource, supporting public methods + * that carry the Cacheable and CacheEvict 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) @@ -67,7 +66,7 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati public AnnotationCacheOperationSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; this.annotationParsers = new LinkedHashSet(1); - this.annotationParsers.add(new SpringCachingAnnotationParser()); + this.annotationParsers.add(new SpringCacheAnnotationParser()); } /** @@ -82,6 +81,7 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati this.annotationParsers = parsers; } + @Override protected CacheOperation findCacheOperation(Class clazz) { return determineCacheOperation(clazz); @@ -120,4 +120,5 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati protected boolean allowPublicMethodsOnly() { return this.publicMethodsOnly; } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheAnnotationParser.java b/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheAnnotationParser.java index aab6ce72554..b016f3009cd 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheAnnotationParser.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheAnnotationParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -28,6 +28,7 @@ import org.springframework.cache.interceptor.CacheOperation; * {@link Cacheable} or {@link CacheEvict}. * * @author Costin Leau + * @since 3.1 */ public interface CacheAnnotationParser { @@ -43,4 +44,5 @@ public interface CacheAnnotationParser { * @see AnnotationCacheOperationSource#determineCacheOperation */ CacheOperation parseCacheAnnotation(AnnotatedElement ae); + } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheEvict.java b/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheEvict.java index dbc109e131e..6414d17efd8 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheEvict.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/annotation/CacheEvict.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -26,10 +26,11 @@ import java.lang.annotation.Target; /** * Annotation indicating that a method (or all methods on a class) trigger(s) * a cache invalidate operation. - * + * * @author Costin Leau + * @since 3.1 */ -@Target( { ElementType.METHOD, ElementType.TYPE }) +@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @@ -44,24 +45,22 @@ public @interface CacheEvict { /** * Spring Expression Language (SpEL) attribute for computing the key dynamically. - *

- * Default is "" meaning all method parameters are considered as a key. + *

Default is "", meaning all method parameters are considered as a key. */ String key() default ""; /** * Spring Expression Language (SpEL) attribute used for conditioning the method caching. - *

- * Default is "" meaning the method is always cached. + *

Default is "", meaning the method is always cached. */ String condition() default ""; /** * Whether or not all the entries inside the cache(s) are removed or not. By * default, only the value under the associated key is removed. - * - * Note that specifying setting this parameter to true and specifying a + *

Note that specifying setting this parameter to true and specifying a * {@link CacheKey key} is not allowed. */ boolean allEntries() default false; -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/annotation/Cacheable.java b/org.springframework.context/src/main/java/org/springframework/cache/annotation/Cacheable.java index a5d007c0570..132352dbaee 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/annotation/Cacheable.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/annotation/Cacheable.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -25,10 +25,12 @@ import java.lang.annotation.Target; /** * Annotation indicating that a method (or all the methods on a class) can be cached. - * The method arguments and signature are used for computing the key while the return instance - * as the cache value. - * + * + *

The method arguments and signature are used for computing the key while the + * returned instance is used as the cache value. + * * @author Costin Leau + * @since 3.1 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @@ -55,4 +57,4 @@ public @interface Cacheable { */ String condition() default ""; -} \ No newline at end of file +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java b/org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java new file mode 100644 index 00000000000..df99b7f73ec --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java @@ -0,0 +1,68 @@ +/* + * Copyright 2002-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 org.springframework.cache.interceptor.CacheEvictOperation; +import org.springframework.cache.interceptor.CacheOperation; +import org.springframework.cache.interceptor.CacheUpdateOperation; +import org.springframework.core.annotation.AnnotationUtils; + +/** + * Strategy implementation for parsing Spring's {@link Cacheable} and {@link CacheEvict} annotations. + * + * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 + */ +@SuppressWarnings("serial") +public class SpringCacheAnnotationParser implements CacheAnnotationParser, Serializable { + + public CacheOperation parseCacheAnnotation(AnnotatedElement ae) { + Cacheable update = AnnotationUtils.getAnnotation(ae, Cacheable.class); + if (update != null) { + return parseCacheableAnnotation(ae, update); + } + CacheEvict evict = AnnotationUtils.getAnnotation(ae, CacheEvict.class); + if (evict != null) { + return parseEvictAnnotation(ae, evict); + } + return null; + } + + CacheUpdateOperation parseCacheableAnnotation(AnnotatedElement ae, Cacheable ann) { + CacheUpdateOperation cuo = new CacheUpdateOperation(); + cuo.setCacheNames(ann.value()); + cuo.setCondition(ann.condition()); + cuo.setKey(ann.key()); + cuo.setName(ae.toString()); + return cuo; + } + + CacheEvictOperation parseEvictAnnotation(AnnotatedElement ae, CacheEvict ann) { + CacheEvictOperation ceo = new CacheEvictOperation(); + ceo.setCacheNames(ann.value()); + ceo.setCondition(ann.condition()); + ceo.setKey(ann.key()); + ceo.setCacheWide(ann.allEntries()); + ceo.setName(ae.toString()); + return ceo; + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCachingAnnotationParser.java b/org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCachingAnnotationParser.java deleted file mode 100644 index 8a5eef1d0d6..00000000000 --- a/org.springframework.context/src/main/java/org/springframework/cache/annotation/SpringCachingAnnotationParser.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; - -import org.springframework.cache.interceptor.CacheEvictOperation; -import org.springframework.cache.interceptor.CacheOperation; -import org.springframework.cache.interceptor.CacheUpdateOperation; - -/** - * Strategy implementation for parsing Spring's {@link Cacheable} and {@link CacheEvict} annotations. - * - * @author Costin Leau - */ -@SuppressWarnings("serial") -public class SpringCachingAnnotationParser implements CacheAnnotationParser, Serializable { - - public CacheOperation parseCacheAnnotation(AnnotatedElement ae) { - Cacheable update = findAnnotation(ae, Cacheable.class); - - if (update != null) { - return parseCacheableAnnotation(ae, update); - } - - CacheEvict invalidate = findAnnotation(ae, CacheEvict.class); - - if (invalidate != null) { - return parseEvictAnnotation(ae, invalidate); - } - - return null; - } - - private T findAnnotation(AnnotatedElement ae, Class annotationType) { - T ann = ae.getAnnotation(annotationType); - if (ann == null) { - for (Annotation metaAnn : ae.getAnnotations()) { - ann = metaAnn.annotationType().getAnnotation(annotationType); - if (ann != null) { - break; - } - } - } - return ann; - } - - CacheUpdateOperation parseCacheableAnnotation(AnnotatedElement target, Cacheable ann) { - CacheUpdateOperation dcud = new CacheUpdateOperation(); - dcud.setCacheNames(ann.value()); - dcud.setCondition(ann.condition()); - dcud.setKey(ann.key()); - dcud.setName(target.toString()); - - return dcud; - } - - CacheEvictOperation parseEvictAnnotation(AnnotatedElement target, CacheEvict ann) { - CacheEvictOperation dcid = new CacheEvictOperation(); - dcid.setCacheNames(ann.value()); - dcid.setCondition(ann.condition()); - dcid.setKey(ann.key()); - dcid.setCacheWide(ann.allEntries()); - dcid.setName(target.toString()); - - return dcid; - } -} \ No newline at end of file diff --git a/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java b/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java index 15e72162c64..945f920ef63 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -17,86 +17,129 @@ package org.springframework.cache.concurrent; import java.io.Serializable; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.springframework.cache.Cache; -import org.springframework.cache.support.DefaultValueWrapper; +import org.springframework.cache.support.ValueWrapperImpl; /** - * Simple {@link Cache} implementation based on the JDK 1.5+ - * java.util.concurrent package. Useful for testing or simple caching scenarios. + * Simple {@link Cache} implementation based on the core JDK + * java.util.concurrent package. + * + *

Useful for testing or simple caching scenarios, typically in combination + * with {@link org.springframework.cache.support.SimpleCacheManager} or + * dynamically through {@link ConcurrentMapCacheManager}. + * + *

Note: As {@link ConcurrentHashMap} (the default implementation used) + * does not allow for null values to be stored, this class will replace + * them with a predefined internal object. This behavior can be changed through the + * {@link #ConcurrentMapCache(String, ConcurrentMap, boolean)} constructor. * - * Note:As {@link ConcurrentHashMap} (the default implementation used) does not allow null values to be stored - * this class will replace them with a predefined, internal object. This behaviour can be changed through the {@link #ConcurrentMapCache(ConcurrentMap, String, boolean)} - * constructor. - * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ public class ConcurrentMapCache implements Cache { - private static class NullHolder implements Serializable { - private static final long serialVersionUID = 1L; - } - private static final Object NULL_HOLDER = new NullHolder(); - private final ConcurrentMap store; + private final String name; + + private final ConcurrentMap store; + private final boolean allowNullValues; - public ConcurrentMapCache() { - this(""); - } + /** + * Create a new ConcurrentMapCache with the specified name. + * @param name the name of the cache + */ public ConcurrentMapCache(String name) { - this(new ConcurrentHashMap(), name, true); + this(name, new ConcurrentHashMap(), true); + } + + /** + * Create a new ConcurrentMapCache with the specified name. + * @param name the name of the cache + */ + public ConcurrentMapCache(String name, boolean allowNullValues) { + this(name, new ConcurrentHashMap(), allowNullValues); } - public ConcurrentMapCache(ConcurrentMap delegate, String name, boolean allowNullValues) { - this.store = delegate; + /** + * Create a new ConcurrentMapCache with the specified name and the + * given internal ConcurrentMap to use. + * @param name the name of the cache + * @param store the ConcurrentMap to use as an internal store + * @param allowNullValues whether to allow null values + * (adapting them to an internal null holder value) + */ + public ConcurrentMapCache(String name, ConcurrentMap store, boolean allowNullValues) { this.name = name; + this.store = store; this.allowNullValues = allowNullValues; } - public String getName() { - return name; - } - public boolean getAllowNullValues() { - return allowNullValues; + public String getName() { + return this.name; } public ConcurrentMap getNativeCache() { - return store; + return this.store; } - public void clear() { - store.clear(); + public boolean isAllowNullValues() { + return this.allowNullValues; } public ValueWrapper get(Object key) { - Object v = store.get(key); - return (v != null ? new DefaultValueWrapper(filterNull(v)) : null); + Object value = this.store.get(key); + return (value != null ? new ValueWrapperImpl(fromStoreValue(value)) : null); } public void put(Object key, Object value) { - if (allowNullValues && value == null) { - Map map = store; - map.put(key, NULL_HOLDER); - } else { - store.put(key, value); - } + this.store.put(key, toStoreValue(value)); } public void evict(Object key) { - store.remove(key); + this.store.remove(key); } - protected Object filterNull(Object val) { - if (allowNullValues && val == NULL_HOLDER) { + public void clear() { + this.store.clear(); + } + + + /** + * Convert the given value from the internal store to a user value + * returned from the get method (adapting null). + * @param userValue the store value + * @return the value to return to the user + */ + protected Object fromStoreValue(Object storeValue) { + if (this.allowNullValues && storeValue == NULL_HOLDER) { return null; } - return val; + return storeValue; + } + + /** + * Convert the given user value, as passed into the put method, + * to a value in the internal store (adapting null). + * @param userValue the given user value + * @return the value to store + */ + protected Object toStoreValue(Object userValue) { + if (this.allowNullValues && userValue == null) { + return NULL_HOLDER; + } + return userValue; } -} \ No newline at end of file + + + private static class NullHolder implements Serializable { + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheFactoryBean.java b/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheFactoryBean.java index 6e6a501dd6e..c7a9474ecdd 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheFactoryBean.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -24,45 +24,78 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.StringUtils; /** - * Factory bean for easy configuration of {@link ConcurrentMapCache} through Spring. - * + * {@link FactoryBean} for easy configuration of a {@link ConcurrentMapCache} + * when used within a Spring container. Can be configured through bean properties; + * uses the assigned Spring bean name as the default cache name. + * + *

Useful for testing or simple caching scenarios, typically in combination + * with {@link org.springframework.cache.support.SimpleCacheManager} or + * dynamically through {@link ConcurrentMapCacheManager}. + * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ -public class ConcurrentMapCacheFactoryBean implements FactoryBean, BeanNameAware, - InitializingBean { +public class ConcurrentMapCacheFactoryBean + implements FactoryBean, BeanNameAware, InitializingBean { private String name = ""; - private ConcurrentMapCache cache; - private ConcurrentMap store; + private ConcurrentMap store; - public void afterPropertiesSet() { - cache = (store == null ? new ConcurrentMapCache(name) : new ConcurrentMapCache(store, name, true)); - } + private boolean allowNullValues = true; + + private ConcurrentMapCache cache; - public ConcurrentMapCache getObject() throws Exception { - return cache; + + /** + * Specify the name of the cache. + *

Default is "" (empty String). + */ + public void setName(String name) { + this.name = name; } - public Class getObjectType() { - return (cache != null ? cache.getClass() : ConcurrentMapCache.class); + /** + * Specify the ConcurrentMap to use as an internal store + * (possibly pre-populated). + *

Default is a standard {@link java.util.concurrent.ConcurrentHashMap}. + */ + public void setStore(ConcurrentMap store) { + this.store = store; } - public boolean isSingleton() { - return true; + /** + * Set whether to allow null values + * (adapting them to an internal null holder value). + *

Default is "true". + */ + public void setAllowNullValues(boolean allowNullValues) { + this.allowNullValues = allowNullValues; } public void setBeanName(String beanName) { - if (!StringUtils.hasText(name)) { + if (!StringUtils.hasLength(this.name)) { setName(beanName); } } - public void setName(String name) { - this.name = name; + public void afterPropertiesSet() { + this.cache = (this.store != null ? new ConcurrentMapCache(this.name, this.store, this.allowNullValues) : + new ConcurrentMapCache(this.name, this.allowNullValues)); } - public void setStore(ConcurrentMap store) { - this.store = store; + + public ConcurrentMapCache getObject() { + return this.cache; } -} \ No newline at end of file + + public Class getObjectType() { + return ConcurrentMapCache.class; + } + + public boolean isSingleton() { + return true; + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java b/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java new file mode 100644 index 00000000000..2d447e6d822 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/cache/concurrent/ConcurrentMapCacheManager.java @@ -0,0 +1,101 @@ +/* + * Copyright 2002-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.concurrent; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +/** + * {@link CacheManager} implementation that lazily builds {@link ConcurrentMapCache} + * instances for each {@link #getCache} request. Also supports a 'static' mode where + * the set of cache names is pre-defined through {@link #setCacheNames}, with no + * dynamic creation of further cache regions at runtime. + * + * @author Juergen Hoeller + * @since 3.1 + */ +public class ConcurrentMapCacheManager implements CacheManager { + + private final ConcurrentMap cacheMap = new ConcurrentHashMap(); + + private boolean dynamic = true; + + + /** + * Construct a dynamic ConcurrentMapCacheManager, + * lazily creating cache instances as they are being requested. + */ + public ConcurrentMapCacheManager() { + } + + /** + * Construct a static ConcurrentMapCacheManager, + * managing caches for the specified cache names only. + */ + public ConcurrentMapCacheManager(String... cacheNames) { + setCacheNames(Arrays.asList(cacheNames)); + } + + + /** + * Specify the set of cache names for this CacheManager's 'static' mode. + *

The number of caches and their names will be fixed after a call to this method, + * with no creation of further cache regions at runtime. + */ + public void setCacheNames(Collection cacheNames) { + if (cacheNames != null) { + for (String name : cacheNames) { + this.cacheMap.put(name, createConcurrentMapCache(name)); + } + this.dynamic = false; + } + } + + public Collection getCacheNames() { + return Collections.unmodifiableSet(this.cacheMap.keySet()); + } + + public Cache getCache(String name) { + Cache cache = this.cacheMap.get(name); + if (cache == null && this.dynamic) { + synchronized (this.cacheMap) { + cache = this.cacheMap.get(name); + if (cache == null) { + cache = createConcurrentMapCache(name); + this.cacheMap.put(name, cache); + } + } + } + return cache; + } + + /** + * Create a new ConcurrentMapCache instance for the specified cache name. + * @param name the name of the cache + * @return the ConcurrentMapCache (or a decorator thereof) + */ + protected Cache createConcurrentMapCache(String name) { + return new ConcurrentMapCache(name); + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java b/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java index 2b49436670d..27e05211f20 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/config/AnnotationDrivenCacheBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -16,7 +16,7 @@ package org.springframework.cache.config; -import static org.springframework.context.annotation.AnnotationConfigUtils.*; +import org.w3c.dom.Element; import org.springframework.aop.config.AopNamespaceUtils; import org.springframework.beans.factory.config.BeanDefinition; @@ -29,7 +29,8 @@ import org.springframework.beans.factory.xml.ParserContext; import org.springframework.cache.annotation.AnnotationCacheOperationSource; import org.springframework.cache.interceptor.BeanFactoryCacheOperationSourceAdvisor; import org.springframework.cache.interceptor.CacheInterceptor; -import org.w3c.dom.Element; + +import static org.springframework.context.annotation.AnnotationConfigUtils.*; /** * {@link org.springframework.beans.factory.xml.BeanDefinitionParser} @@ -43,6 +44,7 @@ import org.w3c.dom.Element; * will result in class-based proxies being created. * * @author Costin Leau + * @since 3.1 */ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser { @@ -111,7 +113,7 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser if (!parserContext.getRegistry().containsBeanDefinition(CACHE_ADVISOR_BEAN_NAME)) { Object eleSource = parserContext.extractSource(element); - // Create the CacheDefinitionSource definition. + // Create the CacheOperationSource definition. RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationCacheOperationSource.class); sourceDef.setSource(eleSource); sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); @@ -122,14 +124,14 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser interceptorDef.setSource(eleSource); interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registerCacheManagerProperty(element, interceptorDef); - interceptorDef.getPropertyValues().add("cacheDefinitionSources", new RuntimeBeanReference(sourceName)); + interceptorDef.getPropertyValues().add("cacheOperationSource", new RuntimeBeanReference(sourceName)); String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef); // Create the CacheAdvisor definition. RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryCacheOperationSourceAdvisor.class); advisorDef.setSource(eleSource); advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - advisorDef.getPropertyValues().add("cacheDefinitionSource", new RuntimeBeanReference(sourceName)); + advisorDef.getPropertyValues().add("cacheOperationSource", new RuntimeBeanReference(sourceName)); advisorDef.getPropertyValues().add("adviceBeanName", interceptorName); if (element.hasAttribute("order")) { advisorDef.getPropertyValues().add("order", element.getAttribute("order")); @@ -145,4 +147,5 @@ class AnnotationDrivenCacheBeanDefinitionParser implements BeanDefinitionParser } } } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/config/CacheNamespaceHandler.java b/org.springframework.context/src/main/java/org/springframework/cache/config/CacheNamespaceHandler.java index a5e69594c05..604a9eeb3b1 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/config/CacheNamespaceHandler.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/config/CacheNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -26,10 +26,12 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport; * Spring cache management facilities. * * @author Costin Leau + * @since 3.1 */ public class CacheNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenCacheBeanDefinitionParser()); } + } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java b/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java index b6d7e476bdb..21d1d822c82 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -21,53 +21,57 @@ import net.sf.ehcache.Element; import net.sf.ehcache.Status; import org.springframework.cache.Cache; -import org.springframework.cache.support.DefaultValueWrapper; +import org.springframework.cache.support.ValueWrapperImpl; import org.springframework.util.Assert; /** * {@link Cache} implementation on top of an {@link Ehcache} instance. - * + * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ public class EhCacheCache implements Cache { private final Ehcache cache; + /** - * Creates a {@link EhCacheCache} instance. - * + * Create an {@link EhCacheCache} instance. * @param ehcache backing Ehcache instance */ public EhCacheCache(Ehcache ehcache) { - Assert.notNull(ehcache, "non null ehcache required"); + Assert.notNull(ehcache, "Ehcache must not be null"); Status status = ehcache.getStatus(); - Assert.isTrue(Status.STATUS_ALIVE.equals(status), "an 'alive' ehcache is required - current cache is " - + status.toString()); + Assert.isTrue(Status.STATUS_ALIVE.equals(status), + "An 'alive' Ehcache is required - current cache is " + status.toString()); this.cache = ehcache; } + public String getName() { - return cache.getName(); + return this.cache.getName(); } public Ehcache getNativeCache() { - return cache; + return this.cache; } public void clear() { - cache.removeAll(); + this.cache.removeAll(); } public ValueWrapper get(Object key) { - Element element = cache.get(key); - return (element != null ? new DefaultValueWrapper(element.getObjectValue()) : null); + Element element = this.cache.get(key); + return (element != null ? new ValueWrapperImpl(element.getObjectValue()) : null); } public void put(Object key, Object value) { - cache.put(new Element(key, value)); + this.cache.put(new Element(key, value)); } public void evict(Object key) { - cache.remove(key); + this.cache.remove(key); } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java b/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java index a623f918d54..65969a36931 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/ehcache/EhCacheCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -27,55 +27,53 @@ import org.springframework.cache.support.AbstractCacheManager; import org.springframework.util.Assert; /** - * CacheManager backed by an Ehcache {@link net.sf.ehcache.CacheManager}. - * + * CacheManager backed by an EhCache {@link net.sf.ehcache.CacheManager}. + * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ public class EhCacheCacheManager extends AbstractCacheManager { private net.sf.ehcache.CacheManager cacheManager; + + /** + * Set the backing EhCache {@link net.sf.ehcache.CacheManager}. + */ + public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + @Override protected Collection loadCaches() { - Assert.notNull(cacheManager, "a backing Ehcache cache manager is required"); - Status status = cacheManager.getStatus(); - + Assert.notNull(this.cacheManager, "A backing EhCache CacheManager is required"); + Status status = this.cacheManager.getStatus(); Assert.isTrue(Status.STATUS_ALIVE.equals(status), - "an 'alive' Ehcache cache manager is required - current cache is " + status.toString()); + "An 'alive' EhCache CacheManager is required - current cache is " + status.toString()); - String[] names = cacheManager.getCacheNames(); + String[] names = this.cacheManager.getCacheNames(); Collection caches = new LinkedHashSet(names.length); - for (String name : names) { - caches.add(new EhCacheCache(cacheManager.getEhcache(name))); + caches.add(new EhCacheCache(this.cacheManager.getEhcache(name))); } - return caches; } + @Override public Cache getCache(String name) { Cache cache = super.getCache(name); if (cache == null) { - // check the Ehcache cache again - // in case the cache was added at runtime - - Ehcache ehcache = cacheManager.getEhcache(name); + // check the EhCache cache again + // (in case the cache was added at runtime) + Ehcache ehcache = this.cacheManager.getEhcache(name); if (ehcache != null) { - // reinitialize cache map - afterPropertiesSet(); - cache = super.getCache(name); + cache = new EhCacheCache(ehcache); + addCache(cache); } } - return cache; } - /** - * Sets the backing Ehcache {@link net.sf.ehcache.CacheManager}. - * - * @param cacheManager backing Ehcache {@link net.sf.ehcache.CacheManager} - */ - public void setCacheManager(net.sf.ehcache.CacheManager cacheManager) { - this.cacheManager = cacheManager; - } -} \ No newline at end of file +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java index 687ec82b635..71b9f167c78 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -41,9 +41,9 @@ import org.springframework.util.ObjectUtils; *

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 + * @since 3.1 */ public abstract class AbstractFallbackCacheOperationSource implements CacheOperationSource { @@ -67,6 +67,7 @@ public abstract class AbstractFallbackCacheOperationSource implements CacheOpera */ final Map attributeCache = new ConcurrentHashMap(); + /** * Determine the caching attribute for this method invocation. *

Defaults to the class's caching attribute if no method attribute is found. @@ -157,6 +158,7 @@ public abstract class AbstractFallbackCacheOperationSource implements CacheOpera return null; } + /** * Subclasses need to implement this to return the caching attribute * for the given method, if any. @@ -183,8 +185,9 @@ public abstract class AbstractFallbackCacheOperationSource implements CacheOpera return false; } + /** - * Default cache key for the CacheOperationDefinition cache. + * Default cache key for the CacheOperation cache. */ private static class DefaultCacheKey { @@ -215,4 +218,5 @@ public abstract class AbstractFallbackCacheOperationSource implements CacheOpera return this.method.hashCode() * 29 + (this.targetClass != null ? this.targetClass.hashCode() : 0); } } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/BeanFactoryCacheOperationSourceAdvisor.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/BeanFactoryCacheOperationSourceAdvisor.java index 21ebfe46adc..9e51071f4c7 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/BeanFactoryCacheOperationSourceAdvisor.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/BeanFactoryCacheOperationSourceAdvisor.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -25,27 +25,29 @@ import org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor; * cache advice bean for methods that are cacheable. * * @author Costin Leau + * @since 3.1 */ @SuppressWarnings("serial") public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { - private CacheOperationSource cacheDefinitionSource; + private CacheOperationSource cacheOperationSource; private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() { @Override protected CacheOperationSource getCacheOperationSource() { - return cacheDefinitionSource; + return cacheOperationSource; } }; + /** * 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; + public void setCacheOperationSource(CacheOperationSource cacheOperationSource) { + this.cacheOperationSource = cacheOperationSource; } /** @@ -59,4 +61,5 @@ public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryP public Pointcut getPointcut() { return this.pointcut; } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java index 82ac363ae0d..758fcb2ba1d 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheAspectSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -25,12 +25,11 @@ import java.util.concurrent.Callable; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.aop.framework.AopProxyUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; -import org.springframework.cache.KeyGenerator; -import org.springframework.cache.support.DefaultKeyGenerator; import org.springframework.expression.EvaluationContext; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -57,6 +56,8 @@ import org.springframework.util.StringUtils; * and CacheDefinitionSource are serializable. * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ public abstract class CacheAspectSupport implements InitializingBean { @@ -64,26 +65,82 @@ public abstract class CacheAspectSupport implements InitializingBean { private CacheManager cacheManager; - private CacheOperationSource cacheDefinitionSource; + private CacheOperationSource cacheOperationSource; private final ExpressionEvaluator evaluator = new ExpressionEvaluator(); private KeyGenerator keyGenerator = new DefaultKeyGenerator(); - private volatile boolean initialized = false; + private boolean initialized = false; + + + /** + * Set the CacheManager that this cache aspect should delegate to. + */ + public void setCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + /** + * Return the CacheManager that this cache aspect delegates to. + */ + public CacheManager getCacheManager() { + return this.cacheManager; + } + + /** + * Set multiple cache definition sources which are used to find the cache + * attributes. Will build a CompositeCachingDefinitionSource for the given sources. + */ + public void setCacheOperationSources(CacheOperationSource... cacheDefinitionSources) { + Assert.notEmpty(cacheDefinitionSources); + this.cacheOperationSource = (cacheDefinitionSources.length > 1 ? + new CompositeCacheOperationSource(cacheDefinitionSources) : cacheDefinitionSources[0]); + } + + /** + * Set the CacheOperationSource for this cache aspect, + * resolving applicable cache operations from annotations or the like. + */ + public void setCacheOperationSource(CacheOperationSource cacheOperationSource) { + this.cacheOperationSource = cacheOperationSource; + } + + /** + * Return the CacheOperationSource for this cache aspect. + */ + public CacheOperationSource getCacheOperationSource() { + return this.cacheOperationSource; + } + + /** + * Set the KeyGenerator for this cache aspect. + * Default is {@link DefaultKeyGenerator}. + */ + public void setKeyGenerator(KeyGenerator keyGenerator) { + this.keyGenerator = keyGenerator; + } + + /** + * Return the KeyGenerator for this cache aspect, + */ + public KeyGenerator getKeyGenerator() { + return this.keyGenerator; + } public void afterPropertiesSet() { if (this.cacheManager == null) { - throw new IllegalStateException("Setting the property 'cacheManager' is required"); + throw new IllegalStateException("'cacheManager' is required"); } - if (this.cacheDefinitionSource == null) { + if (this.cacheOperationSource == null) { throw new IllegalStateException("Either 'cacheDefinitionSource' or 'cacheDefinitionSources' is required: " + "If there are no cacheable methods, then don't use a cache aspect."); } - initialized = true; + this.initialized = true; } + /** * Convenience method to return a String representation of this Method * for use in logging. Can be overridden in subclasses to provide a @@ -98,62 +155,29 @@ public abstract class CacheAspectSupport implements InitializingBean { return ClassUtils.getQualifiedMethodName(specificMethod); } - public CacheManager getCacheManager() { - return cacheManager; - } - - public void setCacheManager(CacheManager cacheManager) { - this.cacheManager = cacheManager; - } - - public CacheOperationSource getCacheDefinitionSource() { - return cacheDefinitionSource; - } - - public KeyGenerator getKeyGenerator() { - return keyGenerator; - } - - public void setKeyGenerator(KeyGenerator keyGenerator) { - this.keyGenerator = keyGenerator; - } - - /** - * Set multiple cache definition sources which are used to find the cache - * attributes. Will build a CompositeCachingDefinitionSource for the given sources. - */ - public void setCacheDefinitionSources(CacheOperationSource... cacheDefinitionSources) { - Assert.notEmpty(cacheDefinitionSources); - this.cacheDefinitionSource = (cacheDefinitionSources.length > 1 ? new CompositeCacheOperationSource( - cacheDefinitionSources) : cacheDefinitionSources[0]); - } - protected Collection getCaches(CacheOperation operation) { Set cacheNames = operation.getCacheNames(); - Collection caches = new ArrayList(cacheNames.size()); - for (String cacheName : cacheNames) { - Cache cache = cacheManager.getCache(cacheName); + Cache cache = this.cacheManager.getCache(cacheName); if (cache == null) { throw new IllegalArgumentException("Cannot find cache named [" + cacheName + "] for " + operation); } caches.add(cache); } - return caches; } protected CacheOperationContext getOperationContext(CacheOperation operation, Method method, Object[] args, Object target, Class targetClass) { + return new CacheOperationContext(operation, method, args, target, targetClass); } protected Object execute(Callable invocation, Object target, Method method, Object[] args) throws Exception { // check whether aspect is enabled // to cope with cases where the AJ is pulled in automatically - - if (!initialized) { + if (!this.initialized) { return invocation.call(); } @@ -161,15 +185,13 @@ public abstract class CacheAspectSupport implements InitializingBean { // get backing class Class targetClass = AopProxyUtils.ultimateTargetClass(target); - if (targetClass == null && target != null) { targetClass = target.getClass(); } - final CacheOperation cacheOp = getCacheDefinitionSource().getCacheOperation(method, targetClass); + final CacheOperation cacheOp = getCacheOperationSource().getCacheOperation(method, targetClass); Object retVal = null; - // analyze caching information if (cacheOp != null) { CacheOperationContext context = getOperationContext(cacheOp, method, args, target, targetClass); @@ -179,11 +201,9 @@ public abstract class CacheAspectSupport implements InitializingBean { // check operation if (cacheOp instanceof CacheUpdateOperation) { Object key = context.generateKey(); - if (log) { logger.trace("Computed cache key " + key + " for definition " + cacheOp); } - if (key == null) { throw new IllegalArgumentException( "Null key returned for cache definition (maybe you are using named params on classes without debug info?) " @@ -196,7 +216,6 @@ public abstract class CacheAspectSupport implements InitializingBean { for (Iterator iterator = caches.iterator(); iterator.hasNext() && !cacheHit;) { Cache cache = iterator.next(); Cache.ValueWrapper wrapper = cache.get(key); - if (wrapper != null) { cacheHit = true; retVal = wrapper.get(); @@ -209,12 +228,12 @@ public abstract class CacheAspectSupport implements InitializingBean { + method); } retVal = invocation.call(); - // update all caches for (Cache cache : caches) { cache.put(key, retVal); } - } else { + } + else { if (log) { logger.trace("Key " + key + " found in cache, returning value " + retVal); } @@ -234,10 +253,11 @@ public abstract class CacheAspectSupport implements InitializingBean { if (evictOp.isCacheWide()) { cache.clear(); if (log) { - logger.trace("Invalidating entire cache for definition " + cacheOp + " on method " - + method); + logger.trace("Invalidating entire cache for definition " + cacheOp + + " on method " + method); } - } else { + } + else { // check key if (key == null) { key = context.generateKey(); @@ -250,9 +270,9 @@ public abstract class CacheAspectSupport implements InitializingBean { } } } - return retVal; - } else { + } + else { if (log) { logger.trace("Cache condition failed on method " + method + " for definition " + cacheOp); } @@ -262,19 +282,22 @@ public abstract class CacheAspectSupport implements InitializingBean { return invocation.call(); } + protected class CacheOperationContext { - private CacheOperation operation; + private final CacheOperation operation; + private final Collection caches; + private final Object target; + private final Method method; + private final Object[] args; // context passed around to avoid multiple creations private final EvaluationContext evalContext; - private final KeyGenerator keyGenerator = CacheAspectSupport.this.keyGenerator; - public CacheOperationContext(CacheOperation operation, Method method, Object[] args, Object target, Class targetClass) { this.operation = operation; @@ -286,39 +309,27 @@ public abstract class CacheAspectSupport implements InitializingBean { this.evalContext = evaluator.createEvaluationContext(caches, method, args, target, targetClass); } - /** - * Evaluates the definition condition. - * - * @param operation - * @return - */ protected boolean hasConditionPassed() { - if (StringUtils.hasText(operation.getCondition())) { - return evaluator.condition(operation.getCondition(), method, evalContext); + if (StringUtils.hasText(this.operation.getCondition())) { + return evaluator.condition(this.operation.getCondition(), this.method, this.evalContext); } return true; } /** - * Computes the key for the given caching definition. - * - * @param operation - * @param method - * method being invoked - * @param objects - * arguments passed during the method invocation + * Computes the key for the given caching operation. * @return generated key (null if none can be generated) */ protected Object generateKey() { - if (StringUtils.hasText(operation.getKey())) { - return evaluator.key(operation.getKey(), method, evalContext); + if (StringUtils.hasText(this.operation.getKey())) { + return evaluator.key(this.operation.getKey(), this.method, this.evalContext); } - - return keyGenerator.extract(target, method, args); + return keyGenerator.extract(this.target, this.method, this.args); } protected Collection getCaches() { - return caches; + return this.caches; } } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheEvictOperation.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheEvictOperation.java index bfbbdc4dbc2..c9c47dcd521 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheEvictOperation.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheEvictOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -17,27 +17,28 @@ package org.springframework.cache.interceptor; /** - * Class describing an 'evict' operation. - * + * Class describing a cache 'evict' operation. + * * @author Costin Leau + * @since 3.1 */ public class CacheEvictOperation extends CacheOperation { private boolean cacheWide = false; - public boolean isCacheWide() { - return cacheWide; - } - public void setCacheWide(boolean cacheWide) { this.cacheWide = cacheWide; } + public boolean isCacheWide() { + return this.cacheWide; + } + @Override protected StringBuilder getOperationDescription() { StringBuilder sb = super.getOperationDescription(); sb.append(","); - sb.append(cacheWide); + sb.append(this.cacheWide); return sb; } } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java index ba81aa927ee..af534a476bf 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheExpressionRootObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -20,53 +20,62 @@ import java.lang.reflect.Method; import java.util.Collection; import org.springframework.cache.Cache; +import org.springframework.util.Assert; /** - * Interface describing the root object used during the expression evaluation. - * + * Class describing the root object used during the expression evaluation. + * * @author Costin Leau + * @since 3.1 */ -interface CacheExpressionRootObject { - - /** - * Returns the name of the method being cached. - * - * @return name of the cached method. - */ - String getMethodName(); - - /** - * Returns the method being cached. - * - * @return method being cached - */ - Method getMethod(); - - /** - * Returns the parameters for this invocation. - * - * @return params for this invocation. - */ - Object[] getParams(); - - /** - * Returns the target instance being cached. - * - * @return target instance - */ - Object getTarget(); - - /** - * Returns the target class. - * - * @return target class - */ - Class getTargetClass(); - - /** - * Returns the caches against which the method is executed. - * - * @return current cache - */ - Collection getCaches(); +class CacheExpressionRootObject { + + private final Collection caches; + + private final Method method; + + private final Object[] args; + + private final Object target; + + private final Class targetClass; + + + public CacheExpressionRootObject( + Collection caches, Method method, Object[] args, Object target, Class targetClass) { + + Assert.notNull(method, "Method is required"); + Assert.notNull(targetClass, "targetClass is required"); + this.method = method; + this.target = target; + this.targetClass = targetClass; + this.args = args; + this.caches = caches; + } + + + public Collection getCaches() { + return this.caches; + } + + public Method getMethod() { + return this.method; + } + + public String getMethodName() { + return this.method.getName(); + } + + public Object[] getArgs() { + return this.args; + } + + public Object getTarget() { + return this.target; + } + + public Class getTargetClass() { + return this.targetClass; + } + } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java index 4fc5b6bcb07..5deefeb725d 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -23,6 +23,8 @@ import java.util.concurrent.Callable; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.springframework.util.ReflectionUtils; + /** * AOP Alliance MethodInterceptor for declarative cache * management using the common Spring caching infrastructure @@ -34,8 +36,10 @@ import org.aopalliance.intercept.MethodInvocation; * in the correct order. * *

CacheInterceptors are thread-safe. - * + * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ @SuppressWarnings("serial") public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable { @@ -44,19 +48,18 @@ public class CacheInterceptor extends CacheAspectSupport implements MethodInterc Method method = invocation.getMethod(); Callable aopAllianceInvocation = new Callable() { - public Object call() throws Exception { try { return invocation.proceed(); - } catch (Throwable th) { - if (th instanceof Exception) { - throw (Exception) th; - } - throw (Error) th; + } + catch (Throwable ex) { + ReflectionUtils.rethrowException(ex); + return null; } } }; return execute(aopAllianceInvocation, invocation.getThis(), method, invocation.getArguments()); } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperation.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperation.java index 569ff2f0fcf..9a06a457bde 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperation.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -115,13 +115,13 @@ public abstract class CacheOperation { protected StringBuilder getOperationDescription() { StringBuilder result = new StringBuilder(); result.append("CacheDefinition["); - result.append(name); + result.append(this.name); result.append("] caches="); - result.append(cacheNames); + result.append(this.cacheNames); result.append(" | condition='"); - result.append(condition); + result.append(this.condition); result.append("' | key='"); - result.append(key); + result.append(this.key); result.append("'"); return result; } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSource.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSource.java index f22c0b11189..0d464275d9f 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSource.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -18,24 +18,25 @@ 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 + * @since 3.1 */ 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 null, in which - * case the declaring class of the method must be used. + * Return the cache operation definition for this method, + * or null if the method is not cacheable. + * @param method the method to introspect + * @param targetClass the target class (may be null, + * in which case the declaring class of the method must be used) * @return {@link CacheOperation} the matching cache operation, * or null if none found */ CacheOperation getCacheOperation(Method method, Class targetClass); + } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSourcePointcut.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSourcePointcut.java index e519e7cb088..cfc84160471 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSourcePointcut.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheOperationSourcePointcut.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -23,10 +23,11 @@ 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. + * A Pointcut that matches if the underlying {@link CacheOperationSource} + * has an attribute for a given method. * * @author Costin Leau + * @since 3.1 */ @SuppressWarnings("serial") abstract class CacheOperationSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { @@ -65,4 +66,5 @@ abstract class CacheOperationSourcePointcut extends StaticMethodMatcherPointcut * To be implemented by subclasses. */ protected abstract CacheOperationSource getCacheOperationSource(); -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheProxyFactoryBean.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheProxyFactoryBean.java index 2460c30d403..5e9bbd0d26d 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheProxyFactoryBean.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheProxyFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -50,7 +50,7 @@ public class CacheProxyFactoryBean extends AbstractSingletonProxyFactoryBean { * @param cacheDefinitionSources cache definition sources */ public void setCacheDefinitionSources(CacheOperationSource... cacheDefinitionSources) { - this.cachingInterceptor.setCacheDefinitionSources(cacheDefinitionSources); + this.cachingInterceptor.setCacheOperationSources(cacheDefinitionSources); } } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheUpdateOperation.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheUpdateOperation.java index 4b11483c030..7229b1a3ae4 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheUpdateOperation.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CacheUpdateOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -17,9 +17,10 @@ package org.springframework.cache.interceptor; /** - * Class describing an 'update' operation. - * + * Class describing a cache 'update' operation. + * * @author Costin Leau + * @since 3.1 */ public class CacheUpdateOperation extends CacheOperation { diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CompositeCacheOperationSource.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CompositeCacheOperationSource.java index d42b8148c57..5215f551501 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CompositeCacheOperationSource.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/CompositeCacheOperationSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -24,40 +24,42 @@ import org.springframework.util.Assert; /** * Composite {@link CacheOperationSource} implementation that iterates * over a given array of {@link CacheOperationSource} instances. - * + * * @author Costin Leau + * @since 3.1 */ @SuppressWarnings("serial") public class CompositeCacheOperationSource implements CacheOperationSource, Serializable { - private final CacheOperationSource[] cacheDefinitionSources; + private final CacheOperationSource[] cacheOperationSources; + /** - * Create a new CompositeCachingDefinitionSource for the given sources. - * @param cacheDefinitionSourcess the CacheDefinitionSource instances to combine + * Create a new CompositeCacheOperationSource for the given sources. + * @param cacheOperationSources the CacheOperationSource instances to combine */ - public CompositeCacheOperationSource(CacheOperationSource[] cacheDefinitionSources) { - Assert.notNull(cacheDefinitionSources, "cacheDefinitionSource array must not be null"); - this.cacheDefinitionSources = cacheDefinitionSources; + public CompositeCacheOperationSource(CacheOperationSource... cacheOperationSources) { + Assert.notEmpty(cacheOperationSources, "cacheOperationSources array must not be empty"); + this.cacheOperationSources = cacheOperationSources; } + /** - * Return the CacheDefinitionSource instances that this - * CompositeCachingDefinitionSource combines. + * Return the CacheOperationSource instances that this CompositeCachingDefinitionSource combines. */ - public final CacheOperationSource[] getCacheDefinitionSources() { - return this.cacheDefinitionSources; + public final CacheOperationSource[] getCacheOperationSources() { + return this.cacheOperationSources; } public CacheOperation getCacheOperation(Method method, Class targetClass) { - for (CacheOperationSource source : cacheDefinitionSources) { + for (CacheOperationSource source : this.cacheOperationSources) { CacheOperation definition = source.getCacheOperation(method, targetClass); if (definition != null) { return definition; } } - return null; } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java deleted file mode 100644 index e668bc964fd..00000000000 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultCacheExpressionRootObject.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.util.Collection; - -import org.springframework.cache.Cache; -import org.springframework.util.Assert; - -/** - * Default implementation of expression root object. - * - * @author Costin Leau - */ -public class DefaultCacheExpressionRootObject implements CacheExpressionRootObject { - - private final Object target; - private final Class targetClass; - private final String methodName; - private final Method method; - private final Collection caches; - private final Object[] args; - - public DefaultCacheExpressionRootObject(Collection caches, Method method, Object[] args, - Object target, Class targetClass) { - Assert.notNull(method, "method is required"); - Assert.notNull(targetClass, "targetClass is required"); - this.method = method; - this.methodName = method.getName(); - this.target = target; - this.targetClass = targetClass; - this.args = args; - this.caches = caches; - } - - public String getMethodName() { - return methodName; - } - - public Collection getCaches() { - return caches; - } - - public Method getMethod() { - return method; - } - - public Object[] getParams() { - return args; - } - - public Object getTarget() { - return target; - } - - public Class getTargetClass() { - return targetClass; - } -} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/support/DefaultKeyGenerator.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultKeyGenerator.java similarity index 75% rename from org.springframework.context/src/main/java/org/springframework/cache/support/DefaultKeyGenerator.java rename to org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultKeyGenerator.java index fd251f85c43..1ebe4f5ec46 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/support/DefaultKeyGenerator.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/DefaultKeyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -14,17 +14,19 @@ * limitations under the License. */ -package org.springframework.cache.support; +package org.springframework.cache.interceptor; import java.lang.reflect.Method; -import org.springframework.cache.KeyGenerator; +import org.springframework.cache.interceptor.KeyGenerator; /** - * Default key generator. Returns 0 if no param is given, the param itself if only one is given or a hash code computed - * from all given params hash code. Uses a constant (53) for null objects. - * + * Default key generator. Returns 0 if no param is given, the param itself if + * only one is given or a hash code computed from all given params hash code. + * Uses a constant (53) for null objects. + * * @author Costin Leau + * @since 3.1 */ public class DefaultKeyGenerator implements KeyGenerator { @@ -32,17 +34,14 @@ public class DefaultKeyGenerator implements KeyGenerator { if (params.length == 1) { return (params[0] == null ? 53 : params[0]); } - if (params.length == 0) { return 0; } - int hashCode = 17; - for (Object object : params) { hashCode = 31 * hashCode + (object == null ? 53 : object.hashCode()); } - return Integer.valueOf(hashCode); } + } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java index 47e95a7dd68..2049ad03863 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/ExpressionEvaluator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -27,51 +27,55 @@ import org.springframework.core.ParameterNameDiscoverer; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; /** * Utility class handling the SpEL expression parsing. * Meant to be used as a reusable, thread-safe component. - * - * Performs internal caching for performance reasons. - * + * + *

Performs internal caching for performance reasons. + * * @author Costin Leau + * @since 3.1 */ class ExpressionEvaluator { private SpelExpressionParser parser = new SpelExpressionParser(); + // shared param discoverer since it caches data internally private ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); private Map conditionCache = new ConcurrentHashMap(); + private Map keyCache = new ConcurrentHashMap(); + private Map targetMethodCache = new ConcurrentHashMap(); - EvaluationContext createEvaluationContext(Collection caches, Method method, Object[] args, - Object target, Class targetClass) { - DefaultCacheExpressionRootObject rootObject = new DefaultCacheExpressionRootObject(caches, method, args, - target, targetClass); - StandardEvaluationContext evaluationContext = new LazyParamAwareEvaluationContext(rootObject, - paramNameDiscoverer, method, args, targetClass, targetMethodCache); - return evaluationContext; + public EvaluationContext createEvaluationContext( + Collection caches, Method method, Object[] args, Object target, Class targetClass) { + + CacheExpressionRootObject rootObject = + new CacheExpressionRootObject(caches, method, args, target, targetClass); + return new LazyParamAwareEvaluationContext(rootObject, + this.paramNameDiscoverer, method, args, targetClass, this.targetMethodCache); } - boolean condition(String conditionExpression, Method method, EvaluationContext evalContext) { - Expression condExp = conditionCache.get(method); + public boolean condition(String conditionExpression, Method method, EvaluationContext evalContext) { + Expression condExp = this.conditionCache.get(method); if (condExp == null) { - condExp = parser.parseExpression(conditionExpression); - conditionCache.put(method, condExp); + condExp = this.parser.parseExpression(conditionExpression); + this.conditionCache.put(method, condExp); } return condExp.getValue(evalContext, boolean.class); } - Object key(String keyExpression, Method method, EvaluationContext evalContext) { - Expression keyExp = keyCache.get(method); + public Object key(String keyExpression, Method method, EvaluationContext evalContext) { + Expression keyExp = this.keyCache.get(method); if (keyExp == null) { - keyExp = parser.parseExpression(keyExpression); - keyCache.put(method, keyExp); + keyExp = this.parser.parseExpression(keyExpression); + this.keyCache.put(method, keyExp); } return keyExp.getValue(evalContext); } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/KeyGenerator.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/KeyGenerator.java similarity index 84% rename from org.springframework.context/src/main/java/org/springframework/cache/KeyGenerator.java rename to org.springframework.context/src/main/java/org/springframework/cache/interceptor/KeyGenerator.java index b520929bb99..45b65343070 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/KeyGenerator.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/KeyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -14,17 +14,19 @@ * limitations under the License. */ -package org.springframework.cache; +package org.springframework.cache.interceptor; import java.lang.reflect.Method; /** * Cache 'key' extractor. Used for creating a key based on the given method * (used as context) and its parameters. - * + * * @author Costin Leau + * @since 3.1 */ public interface KeyGenerator { Object extract(Object target, Method method, Object... params); + } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java index 60c5f75c2b1..9cb14ff7e4b 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/interceptor/LazyParamAwareEvaluationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -28,22 +28,28 @@ import org.springframework.util.ObjectUtils; * Evaluation context class that adds a method parameters as SpEL variables, * in a lazy manner. The lazy nature eliminates unneeded parsing of classes * byte code for parameter discovery. - * - * To limit the creation of objects, an ugly constructor is used (rather then a - * dedicated 'closure'-like class for deferred execution). - * + * + *

To limit the creation of objects, an ugly constructor is used (rather then + * a dedicated 'closure'-like class for deferred execution). + * * @author Costin Leau + * @since 3.1 */ class LazyParamAwareEvaluationContext extends StandardEvaluationContext { private final ParameterNameDiscoverer paramDiscoverer; + private final Method method; + private final Object[] args; - private Class targetClass; - private Map methodCache; + + private final Class targetClass; + + private final Map methodCache; private boolean paramLoaded = false; + LazyParamAwareEvaluationContext(Object rootObject, ParameterNameDiscoverer paramDiscoverer, Method method, Object[] args, Class targetClass, Map methodCache) { super(rootObject); @@ -55,6 +61,7 @@ class LazyParamAwareEvaluationContext extends StandardEvaluationContext { this.methodCache = methodCache; } + /** * Load the param information only when needed. */ @@ -64,42 +71,41 @@ class LazyParamAwareEvaluationContext extends StandardEvaluationContext { if (variable != null) { return variable; } - - if (!paramLoaded) { - paramLoaded = true; + if (!this.paramLoaded) { loadArgsAsVariables(); + this.paramLoaded = true; variable = super.lookupVariable(name); } - return variable; } private void loadArgsAsVariables() { // shortcut if no args need to be loaded - if (ObjectUtils.isEmpty(args)) { + if (ObjectUtils.isEmpty(this.args)) { return; } - Method targetMethod = methodCache.get(method); + Method targetMethod = this.methodCache.get(this.method); if (targetMethod == null) { - targetMethod = AopUtils.getMostSpecificMethod(method, targetClass); + targetMethod = AopUtils.getMostSpecificMethod(this.method, this.targetClass); if (targetMethod == null) { - targetMethod = method; + targetMethod = this.method; } - methodCache.put(method, targetMethod); + this.methodCache.put(this.method, targetMethod); } // save arguments as indexed variables - for (int i = 0; i < args.length; i++) { - super.setVariable("p" + i, args[i]); + for (int i = 0; i < this.args.length; i++) { + setVariable("p" + i, this.args[i]); } - String[] parameterNames = paramDiscoverer.getParameterNames(targetMethod); + String[] parameterNames = this.paramDiscoverer.getParameterNames(targetMethod); // save parameter names (if discovered) if (parameterNames != null) { for (int i = 0; i < parameterNames.length; i++) { - super.setVariable(parameterNames[i], args[i]); + setVariable(parameterNames[i], this.args[i]); } } } -} \ No newline at end of file + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/support/AbstractCacheManager.java b/org.springframework.context/src/main/java/org/springframework/cache/support/AbstractCacheManager.java index 3e393dd8085..e24fd746c02 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/support/AbstractCacheManager.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/support/AbstractCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -29,57 +29,50 @@ import org.springframework.cache.CacheManager; import org.springframework.util.Assert; /** - * Abstract base class implementing the common CacheManager methods. Useful for 'static' environments where the - * backing caches do not change. - * + * Abstract base class implementing the common CacheManager methods. + * Useful for 'static' environments where the backing caches do not change. + * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ public abstract class AbstractCacheManager implements CacheManager, InitializingBean { - // fast lookup by name map - private final ConcurrentMap caches = new ConcurrentHashMap(); - private Collection names; + private final ConcurrentMap cacheMap = new ConcurrentHashMap(); - public void afterPropertiesSet() { - Collection cacheSet = loadCaches(); + private Set cacheNames = new LinkedHashSet(); - Assert.notEmpty(cacheSet); - caches.clear(); + public void afterPropertiesSet() { + Collection caches = loadCaches(); + Assert.notEmpty(caches, "loadCaches must not return an empty Collection"); + this.cacheMap.clear(); // preserve the initial order of the cache names - Set cacheNames = new LinkedHashSet(cacheSet.size()); - - for (Cache cache : cacheSet) { - caches.put(cache.getName(), cache); - cacheNames.add(cache.getName()); + for (Cache cache : caches) { + this.cacheMap.put(cache.getName(), cache); + this.cacheNames.add(cache.getName()); } - - names = Collections.unmodifiableSet(cacheNames); } - /** - * Loads the caches into the cache manager. Occurs at startup. - * The returned collection should not be null. - * - * @param caches the collection of caches handled by the manager - */ - protected abstract Collection loadCaches(); - - /** - * Returns the internal cache map. - * - * @return internal cache map - */ - protected final ConcurrentMap getCacheMap() { - return caches; + protected final void addCache(Cache cache) { + this.cacheMap.put(cache.getName(), cache); + this.cacheNames.add(cache.getName()); } public Cache getCache(String name) { - return caches.get(name); + return this.cacheMap.get(name); } public Collection getCacheNames() { - return names; + return Collections.unmodifiableSet(this.cacheNames); } -} \ No newline at end of file + + + /** + * Load the caches for this cache manager. Occurs at startup. + * The returned collection must not be null. + */ + protected abstract Collection loadCaches(); + +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/support/CompositeCacheManager.java b/org.springframework.context/src/main/java/org/springframework/cache/support/CompositeCacheManager.java index c0fa4a1e111..494e2fce21f 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/support/CompositeCacheManager.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/support/CompositeCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -29,57 +29,59 @@ import org.springframework.util.Assert; /** * Composite {@link CacheManager} implementation that iterates * over a given collection of {@link CacheManager} instances. - * + * * Allows {@link NoOpCacheManager} to be automatically added to the list for handling * the cache declarations without a backing store. - * + * * @author Costin Leau + * @author Juergen Hoeller + * @since 3.1 */ public class CompositeCacheManager implements InitializingBean, CacheManager { private List cacheManagers; - private boolean noOpManager = false; + + private boolean fallbackToNoOpCache = false; + + + public void setCacheManagers(Collection cacheManagers) { + Assert.notEmpty(cacheManagers, "cacheManagers Collection must not be empty"); + this.cacheManagers = new ArrayList(); + this.cacheManagers.addAll(cacheManagers); + } + + /** + * Indicate whether a {@link NoOpCacheManager} should be added at the end of the manager lists. + * In this case, any getCache requests not handled by the configured cache managers will + * be automatically handled by the {@link NoOpCacheManager} (and hence never return null). + */ + public void setFallbackToNoOpCache(boolean fallbackToNoOpCache) { + this.fallbackToNoOpCache = fallbackToNoOpCache; + } public void afterPropertiesSet() { - if (noOpManager) { - cacheManagers.add(new NoOpCacheManager()); + if (this.fallbackToNoOpCache) { + this.cacheManagers.add(new NoOpCacheManager()); } } + public Cache getCache(String name) { - Cache cache = null; - for (CacheManager cacheManager : cacheManagers) { - cache = cacheManager.getCache(name); + for (CacheManager cacheManager : this.cacheManagers) { + Cache cache = cacheManager.getCache(name); if (cache != null) { return cache; } } - - return cache; + return null; } public Collection getCacheNames() { List names = new ArrayList(); - for (CacheManager manager : cacheManagers) { + for (CacheManager manager : this.cacheManagers) { names.addAll(manager.getCacheNames()); } - return Collections.unmodifiableCollection(names); + return Collections.unmodifiableList(names); } - public void setCacheManagers(Collection cacheManagers) { - Assert.notEmpty(cacheManagers, "non-null/empty array required"); - this.cacheManagers = new ArrayList(); - this.cacheManagers.addAll(cacheManagers); - } - - /** - * Indicates whether a {@link NoOpCacheManager} will be added at the end of the manager lists. - * Any cache requests not handled by the configured cache managers will be automatically handled - * by the {@link NoOpCacheManager}. - * - * @param add whether a {@link NoOpCacheManager} instance will be added or not - */ - public void setAddNoOpCache(boolean add) { - this.noOpManager = add; - } -} \ No newline at end of file +} diff --git a/org.springframework.context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java b/org.springframework.context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java index aa3a3230bc6..f59f8fd6b42 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/support/NoOpCacheManager.java @@ -29,11 +29,12 @@ import org.springframework.cache.CacheManager; /** * A basic, no operation {@link CacheManager} implementation suitable for disabling caching, * typically used for backing cache declarations without an actual backing store. - * - * Will simply accept any items into the cache not actually storing them. - * - * @see CompositeCacheManager + * + *

Will simply accept any items into the cache not actually storing them. + * * @author Costin Leau + * @since 3.1 + * @see CompositeCacheManager */ public class NoOpCacheManager implements CacheManager { diff --git a/org.springframework.context/src/main/java/org/springframework/cache/support/SimpleCacheManager.java b/org.springframework.context/src/main/java/org/springframework/cache/support/SimpleCacheManager.java index 3b910fa6fb7..3350309cd8c 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/support/SimpleCacheManager.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/support/SimpleCacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2002-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. @@ -21,21 +21,26 @@ import java.util.Collection; import org.springframework.cache.Cache; /** - * Simple cache manager working against a given collection of caches. Useful for testing or simple - * caching declarations. - * + * Simple cache manager working against a given collection of caches. + * Useful for testing or simple caching declarations. + * * @author Costin Leau + * @since 3.1 */ public class SimpleCacheManager extends AbstractCacheManager { private Collection caches; + /** + * Specify the collection of Cache instances to use for this CacheManager. + */ + public void setCaches(Collection caches) { + this.caches = caches; + } + @Override protected Collection loadCaches() { - return caches; + return this.caches; } - public void setCaches(Collection caches) { - this.caches = caches; - } } diff --git a/org.springframework.context/src/main/java/org/springframework/cache/support/DefaultValueWrapper.java b/org.springframework.context/src/main/java/org/springframework/cache/support/ValueWrapperImpl.java similarity index 70% rename from org.springframework.context/src/main/java/org/springframework/cache/support/DefaultValueWrapper.java rename to org.springframework.context/src/main/java/org/springframework/cache/support/ValueWrapperImpl.java index a1c2e967e00..ec444700a68 100644 --- a/org.springframework.context/src/main/java/org/springframework/cache/support/DefaultValueWrapper.java +++ b/org.springframework.context/src/main/java/org/springframework/cache/support/ValueWrapperImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2002-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. @@ -19,19 +19,21 @@ package org.springframework.cache.support; import org.springframework.cache.Cache.ValueWrapper; /** - * Default implementation for {@link org.springframework.cache.Cache.ValueWrapper}. - * + * Straightforward implementation of {@link org.springframework.cache.Cache.ValueWrapper}. + * * @author Costin Leau + * @since 3.1 */ -public class DefaultValueWrapper implements ValueWrapper { +public class ValueWrapperImpl implements ValueWrapper { private final Object value; - public DefaultValueWrapper(Object value) { + public ValueWrapperImpl(Object value) { this.value = value; } public Object get() { - return value; + return this.value; } + } diff --git a/org.springframework.context/src/test/java/org/springframework/cache/NoOpCacheManagerTest.java b/org.springframework.context/src/test/java/org/springframework/cache/NoOpCacheManagerTests.java similarity index 94% rename from org.springframework.context/src/test/java/org/springframework/cache/NoOpCacheManagerTest.java rename to org.springframework.context/src/test/java/org/springframework/cache/NoOpCacheManagerTests.java index ae1572e7c1f..2de234ebe5b 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/NoOpCacheManagerTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/NoOpCacheManagerTests.java @@ -24,7 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.cache.support.NoOpCacheManager; -public class NoOpCacheManagerTest { +public class NoOpCacheManagerTests { private CacheManager manager; diff --git a/org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTest.java b/org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java similarity index 79% rename from org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTest.java rename to org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java index ba22c8c0fe8..0669bc0c080 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentCacheTests.java @@ -20,16 +20,16 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.springframework.cache.Cache; -import org.springframework.cache.vendor.AbstractNativeCacheTest; +import org.springframework.cache.vendor.AbstractNativeCacheTests; /** * @author Costin Leau */ -public class ConcurrentCacheTest extends AbstractNativeCacheTest> { +public class ConcurrentCacheTests extends AbstractNativeCacheTests> { @Override protected Cache createCache(ConcurrentMap nativeCache) { - return new ConcurrentMapCache(nativeCache, CACHE_NAME, true); + return new ConcurrentMapCache(CACHE_NAME, nativeCache, true); } @Override diff --git a/org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java b/org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java new file mode 100644 index 00000000000..69b66d41ccb --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/cache/concurrent/ConcurrentMapCacheManagerTests.java @@ -0,0 +1,63 @@ +/* + * Copyright 2002-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.concurrent; + +import org.junit.Test; + +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +import static org.junit.Assert.*; + +/** + * @author Juergen Hoeller + */ +public class ConcurrentMapCacheManagerTests { + + @Test + public void testDynamicMode() { + CacheManager cm = new ConcurrentMapCacheManager(); + Cache cache1 = cm.getCache("c1"); + assertTrue(cache1 instanceof ConcurrentMapCache); + Cache cache1again = cm.getCache("c1"); + assertSame(cache1again, cache1); + Cache cache2 = cm.getCache("c2"); + assertTrue(cache2 instanceof ConcurrentMapCache); + Cache cache2again = cm.getCache("c2"); + assertSame(cache2again, cache2); + Cache cache3 = cm.getCache("c3"); + assertTrue(cache3 instanceof ConcurrentMapCache); + Cache cache3again = cm.getCache("c3"); + assertSame(cache3again, cache3); + } + + @Test + public void testStaticMode() { + ConcurrentMapCacheManager cm = new ConcurrentMapCacheManager("c1", "c2"); + Cache cache1 = cm.getCache("c1"); + assertTrue(cache1 instanceof ConcurrentMapCache); + Cache cache1again = cm.getCache("c1"); + assertSame(cache1again, cache1); + Cache cache2 = cm.getCache("c2"); + assertTrue(cache2 instanceof ConcurrentMapCache); + Cache cache2again = cm.getCache("c2"); + assertSame(cache2again, cache2); + Cache cache3 = cm.getCache("c3"); + assertNull(cache3); + } + +} diff --git a/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTest.java b/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTests.java similarity index 95% rename from org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTest.java rename to org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTests.java index 6d5ba97a625..319ae286b1c 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/config/AbstractAnnotationTests.java @@ -31,7 +31,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * * @author Costin Leau */ -public abstract class AbstractAnnotationTest { +public abstract class AbstractAnnotationTests { protected ApplicationContext ctx; diff --git a/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationNamespaceDrivenTest.java b/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationNamespaceDrivenTests.java similarity index 88% rename from org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationNamespaceDrivenTest.java rename to org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationNamespaceDrivenTests.java index 1348580e12d..a30838f743d 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationNamespaceDrivenTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationNamespaceDrivenTests.java @@ -20,7 +20,7 @@ package org.springframework.cache.config; /** * @author Costin Leau */ -public class AnnotationNamespaceDrivenTest extends AbstractAnnotationTest { +public class AnnotationNamespaceDrivenTests extends AbstractAnnotationTests { @Override protected String getConfig() { diff --git a/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationTest.java b/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationTests.java similarity index 89% rename from org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationTest.java rename to org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationTests.java index 1d69e2b0521..97c84e894fc 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/config/AnnotationTests.java @@ -20,7 +20,7 @@ package org.springframework.cache.config; /** * @author Costin Leau */ -public class AnnotationTest extends AbstractAnnotationTest { +public class AnnotationTests extends AbstractAnnotationTests { @Override protected String getConfig() { diff --git a/org.springframework.context/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTest.java b/org.springframework.context/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java similarity index 88% rename from org.springframework.context/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTest.java rename to org.springframework.context/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java index 220ddc2f04f..e007e1f5c61 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/ehcache/EhCacheCacheTests.java @@ -22,14 +22,14 @@ import net.sf.ehcache.Element; import org.junit.Test; import org.springframework.cache.Cache; -import org.springframework.cache.vendor.AbstractNativeCacheTest; +import org.springframework.cache.vendor.AbstractNativeCacheTests; /** * Integration test for EhCache cache. * * @author Costin Leau */ -public class EhCacheCacheTest extends AbstractNativeCacheTest { +public class EhCacheCacheTests extends AbstractNativeCacheTests { @Override protected Ehcache createNativeCache() throws Exception { diff --git a/org.springframework.context/src/test/java/org/springframework/cache/vendor/AbstractNativeCacheTest.java b/org.springframework.context/src/test/java/org/springframework/cache/vendor/AbstractNativeCacheTests.java similarity index 93% rename from org.springframework.context/src/test/java/org/springframework/cache/vendor/AbstractNativeCacheTest.java rename to org.springframework.context/src/test/java/org/springframework/cache/vendor/AbstractNativeCacheTests.java index 45832d66cca..e4bf138c198 100644 --- a/org.springframework.context/src/test/java/org/springframework/cache/vendor/AbstractNativeCacheTest.java +++ b/org.springframework.context/src/test/java/org/springframework/cache/vendor/AbstractNativeCacheTests.java @@ -27,7 +27,7 @@ import org.springframework.cache.Cache; * * @author Costin Leau */ -public abstract class AbstractNativeCacheTest { +public abstract class AbstractNativeCacheTests { protected T nativeCache; protected Cache cache; diff --git a/org.springframework.context/src/test/resources/org/springframework/cache/config/annotationDrivenCacheConfig.xml b/org.springframework.context/src/test/resources/org/springframework/cache/config/annotationDrivenCacheConfig.xml index 167f778fe62..db0415562f9 100644 --- a/org.springframework.context/src/test/resources/org/springframework/cache/config/annotationDrivenCacheConfig.xml +++ b/org.springframework.context/src/test/resources/org/springframework/cache/config/annotationDrivenCacheConfig.xml @@ -17,11 +17,11 @@ - + - +