提交 26dbfba6 编写于 作者: C Costin Leau

SPR-8477

+ add no-op cache implementations suitable for cache declarations w/o a backing store
上级 a58bd307
......@@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.util.Assert;
......@@ -29,11 +30,21 @@ 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
*/
public class CompositeCacheManager implements CacheManager {
public class CompositeCacheManager implements InitializingBean, CacheManager {
private List<CacheManager> cacheManagers;
private boolean noOpManager = false;
private CacheManager[] cacheManagers;
public void afterPropertiesSet() {
if (noOpManager) {
cacheManagers.add(new NoOpCacheManager());
}
}
public Cache getCache(String name) {
Cache cache = null;
......@@ -55,8 +66,20 @@ public class CompositeCacheManager implements CacheManager {
return Collections.unmodifiableCollection(names);
}
public void setCacheManagers(CacheManager[] cacheManagers) {
public void setCacheManagers(Collection<CacheManager> cacheManagers) {
Assert.notEmpty(cacheManagers, "non-null/empty array required");
this.cacheManagers = cacheManagers.clone();
this.cacheManagers = new ArrayList<CacheManager>();
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
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache.support;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.springframework.cache.Cache;
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
* @author Costin Leau
*/
public class NoOpCacheManager implements CacheManager {
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
private Set<String> names = new LinkedHashSet<String>();
private static class NoOpCache implements Cache {
private final String name;
public NoOpCache(String name) {
this.name = name;
}
public void clear() {
}
public void evict(Object key) {
}
public ValueWrapper get(Object key) {
return null;
}
public String getName() {
return name;
}
public Object getNativeCache() {
return null;
}
public void put(Object key, Object value) {
}
}
/**
* {@inheritDoc}
*
* This implementation always returns a {@link Cache} implementation that will not
* store items. Additionally, the request cache will be remembered by the manager for consistency.
*/
public Cache getCache(String name) {
Cache cache = caches.get(name);
if (cache == null) {
caches.putIfAbsent(name, new NoOpCache(name));
synchronized (names) {
names.add(name);
}
}
return caches.get(name);
}
/**
* {@inheritDoc}
*
* This implementation returns the name of the caches previously requested.
*/
public Collection<String> getCacheNames() {
return Collections.unmodifiableSet(names);
}
}
\ No newline at end of file
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cache;
import static org.junit.Assert.*;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cache.support.NoOpCacheManager;
public class NoOpCacheManagerTest {
private CacheManager manager;
@Before
public void setup() {
manager = new NoOpCacheManager();
}
@Test
public void testGetCache() throws Exception {
Cache cache = manager.getCache("bucket");
assertNotNull(cache);
assertSame(cache, manager.getCache("bucket"));
}
@Test
public void testNoOpCache() throws Exception {
String name = UUID.randomUUID().toString();
Cache cache = manager.getCache(name);
assertEquals(name, cache.getName());
Object key = new Object();
cache.put(key, new Object());
assertNull(cache.get(key));
assertNull(cache.getNativeCache());
}
@Test
public void testCacheName() throws Exception {
String name = "bucket";
assertFalse(manager.getCacheNames().contains(name));
manager.getCache(name);
assertTrue(manager.getCacheNames().contains(name));
}
}
......@@ -383,6 +383,7 @@ public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)]]><
</section>
</section>
<section id="cache-store-configuration">
<title>Configuring the cache storage</title>
......@@ -429,6 +430,27 @@ public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)]]><
implementation. Note the entire ehcache-specific configuration is read from the resource <literal>ehcache.xml</literal>.</para>
</section>
<section id="cache-store-configuration-noop">
<title>Dealing with caches without a backing store</title>
<para>Sometimes when switching environments or doing testing, one might have cache declarations without an actual backing cache configured. As this is an invalid configuration, at runtime an
exception will be through since the caching infrastructure is unable to find a suitable store. In situations like this, rather then removing the cache declarations (which can prove tedious),
one can wire in a simple, dummy cache that performs no caching - that is, forces the cached methods to be executed every time:</para>
<programlisting language="xml"><![CDATA[<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers"><list>
<ref bean="jdkCache"/>
<ref bean="gemfireCache"/>
</list></property>
<property name="addNoOpCache" value="true"/>
</bean>]]></programlisting>
<para>The <literal>CompositeCacheManager</literal> above chains multiple <literal>CacheManager</literal>s and aditionally, through the <literal>addNoOpManager</literal> flag, adds a
<emphasis>no op</emphasis> cache that for all the definitions not handled by the configured cache managers. That is, every cache definition not found in either <literal>jdkCache</literal>
or <literal>gemfireCache</literal> (configured above) will be handled by the no op cache, which will not store any information causing the target method to be executed every time.
</para>
</section>
</section>
<section id="cache-plug">
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册