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:
parent
66e1c8c743
commit
903928e504
|
|
@ -1,23 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.springframework.context</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.springframework.context</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -24,28 +24,28 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
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
|
||||
*/
|
||||
public class ConcurrentCacheFactoryBean<K, V> implements FactoryBean<ConcurrentCache<K, V>>, BeanNameAware,
|
||||
public class ConcurrentCacheFactoryBean<K, V> implements FactoryBean<ConcurrentMapCache<K, V>>, BeanNameAware,
|
||||
InitializingBean {
|
||||
|
||||
private String name = "";
|
||||
private ConcurrentCache<K, V> cache;
|
||||
private ConcurrentMapCache<K, V> cache;
|
||||
|
||||
private ConcurrentMap<K, V> store;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return (cache != null ? cache.getClass() : ConcurrentCache.class);
|
||||
return (cache != null ? cache.getClass() : ConcurrentMapCache.class);
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
|
|
|
|||
|
|
@ -14,85 +14,84 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cache.support;
|
||||
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.interceptor.DefaultValueWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class delegating most of the {@link Map}-like methods
|
||||
* to the underlying cache.
|
||||
*
|
||||
* <b>Note:</b>Allows null values to be stored even (for cases where the
|
||||
* underlying cache does not support them) as long as arbitrary serialized
|
||||
* objects are supported.
|
||||
* Simple {@link Cache} implementation based on the JDK 1.5+
|
||||
* java.util.concurrent package. Useful for testing or simple caching scenarios.
|
||||
*
|
||||
* <b>Note:</b>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
|
||||
*/
|
||||
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 final long serialVersionUID = 1L;
|
||||
}
|
||||
|
||||
public static final Object NULL_HOLDER = new NullHolder();
|
||||
|
||||
private final Map<K, V> delegate;
|
||||
private static final Object NULL_HOLDER = new NullHolder();
|
||||
private final ConcurrentMap<K, V> store;
|
||||
private final String name;
|
||||
private final boolean allowNullValues;
|
||||
|
||||
/**
|
||||
* Creates a new instance using the given delegate.
|
||||
*
|
||||
* @param <D> map type
|
||||
* @param delegate map delegate
|
||||
*/
|
||||
public <D extends Map<K, V>> AbstractDelegatingCache(D delegate) {
|
||||
this(delegate, false);
|
||||
public ConcurrentMapCache() {
|
||||
this("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance using the given delegate.
|
||||
*
|
||||
* @param <D> map type
|
||||
* @param delegate map delegate
|
||||
* @param allowNullValues flag indicating whether null values should be replaced or not
|
||||
*/
|
||||
public <D extends Map<K, V>> AbstractDelegatingCache(D delegate, boolean allowNullValues) {
|
||||
Assert.notNull(delegate);
|
||||
this.delegate = delegate;
|
||||
public ConcurrentMapCache(String name) {
|
||||
this(new ConcurrentHashMap<K, V>(), name, true);
|
||||
}
|
||||
|
||||
public ConcurrentMapCache(ConcurrentMap<K, V> delegate, String name, boolean allowNullValues) {
|
||||
this.store = delegate;
|
||||
this.name = name;
|
||||
this.allowNullValues = allowNullValues;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean getAllowNullValues() {
|
||||
return allowNullValues;
|
||||
}
|
||||
|
||||
public ConcurrentMap<K, V> getNativeCache() {
|
||||
return store;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
delegate.clear();
|
||||
store.clear();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void put(K key, V value) {
|
||||
if (allowNullValues && value == null) {
|
||||
Map map = delegate;
|
||||
Map map = store;
|
||||
map.put(key, NULL_HOLDER);
|
||||
}
|
||||
else {
|
||||
delegate.put(key, value);
|
||||
} else {
|
||||
store.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void evict(Object key) {
|
||||
delegate.remove(key);
|
||||
store.remove(key);
|
||||
}
|
||||
|
||||
protected V filterNull(V val) {
|
||||
|
|
@ -29,7 +29,7 @@ public class ConcurrentCacheTest extends AbstractNativeCacheTest<ConcurrentMap<O
|
|||
|
||||
@Override
|
||||
protected Cache createCache(ConcurrentMap<Object, Object> nativeCache) {
|
||||
return new ConcurrentCache(nativeCache, CACHE_NAME);
|
||||
return new ConcurrentMapCache(nativeCache, CACHE_NAME, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue