revised cache abstraction

- removed AbstractDelegatingCache (a cache is not a map, no need to offer a template)
+ renamed ConcurrentCache to ConcurrentCacheMap

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4325 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Costin Leau 2011-05-18 17:43:13 +00:00
parent 66e1c8c743
commit 903928e504
5 changed files with 72 additions and 124 deletions

View File

@ -5,6 +5,11 @@
<projects> <projects>
</projects> </projects>
<buildSpec> <buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand> <buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name> <name>org.eclipse.jdt.core.javabuilder</name>
<arguments> <arguments>
@ -19,5 +24,6 @@
<natures> <natures>
<nature>org.springframework.ide.eclipse.core.springnature</nature> <nature>org.springframework.ide.eclipse.core.springnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures> </natures>
</projectDescription> </projectDescription>

View File

@ -1,57 +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.concurrent;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.springframework.cache.Cache;
import org.springframework.cache.support.AbstractDelegatingCache;
/**
* Simple {@link Cache} implementation based on the JDK 1.5+
* java.util.concurrent package. Useful for testing or simple caching scenarios.
*
* @author Costin Leau
*/
public class ConcurrentCache<K, V> extends AbstractDelegatingCache<K, V> {
private final ConcurrentMap<K, V> store;
private final String name;
public ConcurrentCache() {
this("");
}
public ConcurrentCache(String name) {
this(new ConcurrentHashMap<K, V>(), name);
}
public ConcurrentCache(ConcurrentMap<K, V> delegate, String name) {
super(delegate, true);
this.store = delegate;
this.name = name;
}
public String getName() {
return name;
}
public ConcurrentMap<K, V> getNativeCache() {
return store;
}
}

View File

@ -24,28 +24,28 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
* Factory bean for easy configuration of {@link ConcurrentCache} through Spring. * Factory bean for easy configuration of {@link ConcurrentMapCache} through Spring.
* *
* @author Costin Leau * @author Costin Leau
*/ */
public class ConcurrentCacheFactoryBean<K, V> implements FactoryBean<ConcurrentCache<K, V>>, BeanNameAware, public class ConcurrentCacheFactoryBean<K, V> implements FactoryBean<ConcurrentMapCache<K, V>>, BeanNameAware,
InitializingBean { InitializingBean {
private String name = ""; private String name = "";
private ConcurrentCache<K, V> cache; private ConcurrentMapCache<K, V> cache;
private ConcurrentMap<K, V> store; private ConcurrentMap<K, V> store;
public void afterPropertiesSet() { public void afterPropertiesSet() {
cache = (store == null ? new ConcurrentCache<K, V>(name) : new ConcurrentCache<K, V>(store, name)); cache = (store == null ? new ConcurrentMapCache<K, V>(name) : new ConcurrentMapCache<K, V>(store, name, true));
} }
public ConcurrentCache<K, V> getObject() throws Exception { public ConcurrentMapCache<K, V> getObject() throws Exception {
return cache; return cache;
} }
public Class<?> getObjectType() { public Class<?> getObjectType() {
return (cache != null ? cache.getClass() : ConcurrentCache.class); return (cache != null ? cache.getClass() : ConcurrentMapCache.class);
} }
public boolean isSingleton() { public boolean isSingleton() {

View File

@ -14,85 +14,84 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.cache.support; package org.springframework.cache.concurrent;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.interceptor.DefaultValueWrapper; import org.springframework.cache.interceptor.DefaultValueWrapper;
import org.springframework.util.Assert;
/** /**
* Abstract base class delegating most of the {@link Map}-like methods * Simple {@link Cache} implementation based on the JDK 1.5+
* to the underlying cache. * java.util.concurrent package. Useful for testing or simple caching scenarios.
* *
* <b>Note:</b>Allows null values to be stored even (for cases where the * <b>Note:</b>As {@link ConcurrentHashMap} (the default implementation used) does not allow null values to be stored
* underlying cache does not support them) as long as arbitrary serialized * this class will replace them with a predefined, internal object. This behaviour can be changed through the {@link #ConcurrentMapCache(ConcurrentMap, String, boolean)}
* objects are supported. * constructor.
* *
* @author Costin Leau * @author Costin Leau
*/ */
public abstract class AbstractDelegatingCache<K, V> implements Cache<K, V> { public class ConcurrentMapCache<K, V> implements Cache<K, V> {
private static class NullHolder implements Serializable { private static class NullHolder implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }
public static final Object NULL_HOLDER = new NullHolder(); private static final Object NULL_HOLDER = new NullHolder();
private final ConcurrentMap<K, V> store;
private final Map<K, V> delegate; private final String name;
private final boolean allowNullValues; private final boolean allowNullValues;
/** public ConcurrentMapCache() {
* Creates a new instance using the given delegate. this("");
*
* @param <D> map type
* @param delegate map delegate
*/
public <D extends Map<K, V>> AbstractDelegatingCache(D delegate) {
this(delegate, false);
} }
/** public ConcurrentMapCache(String name) {
* Creates a new instance using the given delegate. this(new ConcurrentHashMap<K, V>(), name, true);
* }
* @param <D> map type
* @param delegate map delegate public ConcurrentMapCache(ConcurrentMap<K, V> delegate, String name, boolean allowNullValues) {
* @param allowNullValues flag indicating whether null values should be replaced or not this.store = delegate;
*/ this.name = name;
public <D extends Map<K, V>> AbstractDelegatingCache(D delegate, boolean allowNullValues) {
Assert.notNull(delegate);
this.delegate = delegate;
this.allowNullValues = allowNullValues; this.allowNullValues = allowNullValues;
} }
public String getName() {
return name;
}
public boolean getAllowNullValues() { public boolean getAllowNullValues() {
return allowNullValues; return allowNullValues;
} }
public ConcurrentMap<K, V> getNativeCache() {
return store;
}
public void clear() { public void clear() {
delegate.clear(); store.clear();
} }
public ValueWrapper<V> get(Object key) { public ValueWrapper<V> get(Object key) {
V v = delegate.get(key); V v = store.get(key);
return (v != null ? new DefaultValueWrapper<V>(filterNull(v)) : null); return (v != null ? new DefaultValueWrapper<V>(filterNull(v)) : null);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void put(K key, V value) { public void put(K key, V value) {
if (allowNullValues && value == null) { if (allowNullValues && value == null) {
Map map = delegate; Map map = store;
map.put(key, NULL_HOLDER); map.put(key, NULL_HOLDER);
} } else {
else { store.put(key, value);
delegate.put(key, value);
} }
} }
public void evict(Object key) { public void evict(Object key) {
delegate.remove(key); store.remove(key);
} }
protected V filterNull(V val) { protected V filterNull(V val) {

View File

@ -29,7 +29,7 @@ public class ConcurrentCacheTest extends AbstractNativeCacheTest<ConcurrentMap<O
@Override @Override
protected Cache createCache(ConcurrentMap<Object, Object> nativeCache) { protected Cache createCache(ConcurrentMap<Object, Object> nativeCache) {
return new ConcurrentCache(nativeCache, CACHE_NAME); return new ConcurrentMapCache(nativeCache, CACHE_NAME, true);
} }
@Override @Override