Add custom cache manager per cache operation

It is now possible to specify the CacheManager to use per operation.
The related cache annotation now has an extra attribute that defines
the name of the CacheManager bean to use.  The cache manager that
was previously used is therefore a 'default' cache manager (i.e. the
one to use if no custom cache manager has been set on the operation).

Issue: SPR-8696
This commit is contained in:
Stephane Nicoll
2014-02-21 14:24:00 +01:00
parent 81c208098f
commit f06cad91c0
21 changed files with 243 additions and 31 deletions

View File

@@ -34,6 +34,7 @@ import org.springframework.util.ReflectionUtils;
/**
* @author Costin Leau
* @author Stephane Nicoll
*/
public class AnnotationCacheOperationSourceTests {
@@ -116,6 +117,22 @@ public class AnnotationCacheOperationSourceTests {
}
}
@Test
public void testCustomCacheManager() {
Collection<CacheOperation> ops = getOps("customCacheManager");
assertEquals(1, ops.size());
CacheOperation cacheOperation = ops.iterator().next();
assertEquals("Custom cache manager not set", "custom", cacheOperation.getCacheManager());
}
@Test
public void testCustomCacheManagerInherited() {
Collection<CacheOperation> ops = getOps("customCacheManagerInherited");
assertEquals(1, ops.size());
CacheOperation cacheOperation = ops.iterator().next();
assertEquals("Custom cache manager not set", "custom", cacheOperation.getCacheManager());
}
private static class AnnotatedClass {
@Cacheable("test")
public void singular() {
@@ -134,6 +151,10 @@ public class AnnotationCacheOperationSourceTests {
public void customKeyGenerator() {
}
@Cacheable(value = "test", cacheManager = "custom")
public void customCacheManager() {
}
@EvictFoo
public void singleStereotype() {
}
@@ -155,6 +176,10 @@ public class AnnotationCacheOperationSourceTests {
@Cacheable(value = "test", key = "#root.methodName", keyGenerator = "custom")
public void invalidKeyAndKeyGeneratorSet() {
}
@CacheableFooCustomCacheManager
public void customCacheManagerInherited() {
}
}
@Retention(RetentionPolicy.RUNTIME)
@@ -169,6 +194,13 @@ public class AnnotationCacheOperationSourceTests {
public @interface CacheableFooCustomKeyGenerator {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Cacheable(value = "foo", cacheManager = "custom")
public @interface CacheableFooCustomCacheManager {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@CacheEvict(value = "foo")

View File

@@ -36,6 +36,7 @@ import org.springframework.context.ApplicationContext;
* @author Costin Leau
* @author Chris Beams
* @author Phillip Webb
* @author Stephane Nicoll
*/
public abstract class AbstractAnnotationTests {
@@ -47,6 +48,8 @@ public abstract class AbstractAnnotationTests {
protected CacheManager cm;
protected CacheManager customCm;
/** @return a refreshed application context */
protected abstract ApplicationContext getApplicationContext();
@@ -55,7 +58,9 @@ public abstract class AbstractAnnotationTests {
ctx = getApplicationContext();
cs = ctx.getBean("service", CacheableService.class);
ccs = ctx.getBean("classService", CacheableService.class);
cm = ctx.getBean(CacheManager.class);
cm = ctx.getBean("cacheManager", CacheManager.class);
customCm = ctx.getBean("customCacheManager", CacheManager.class);
Collection<String> cn = cm.getCacheNames();
assertTrue(cn.contains("default"));
assertTrue(cn.contains("secondary"));
@@ -591,6 +596,26 @@ public abstract class AbstractAnnotationTests {
}
}
@Test
public void testCustomCacheManager() {
Object key = new Object();
Object r1 = cs.customCacheManager(key);
assertSame(r1, cs.customCacheManager(key));
Cache cache = customCm.getCache("default");
assertNotNull(cache.get(key));
}
@Test
public void testUnknownCustomCacheManager() {
try {
Object param = new Object();
cs.unknownCustomCacheManager(param);
fail("should have failed with NoSuchBeanDefinitionException");
} catch (NoSuchBeanDefinitionException e) {
// expected
}
}
@Test
public void testNullArg() throws Exception {
testNullArg(cs);

View File

@@ -26,6 +26,7 @@ import org.springframework.cache.annotation.Caching;
/**
* @author Costin Leau
* @author Phillip Webb
* @author Stephane Nicoll
*/
@Cacheable("default")
public class AnnotatedClassCacheableService implements CacheableService<Object> {
@@ -119,6 +120,18 @@ public class AnnotatedClassCacheableService implements CacheableService<Object>
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", cacheManager = "customCacheManager")
public Object customCacheManager(Object arg1) {
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", cacheManager = "unknownBeanName")
public Object unknownCustomCacheManager(Object arg1) {
return counter.getAndIncrement();
}
@Override
@CachePut("default")
public Object update(Object arg1) {

View File

@@ -21,6 +21,7 @@ package org.springframework.cache.config;
*
* @author Costin Leau
* @author Phillip Webb
* @author Stephane Nicoll
*/
public interface CacheableService<T> {
@@ -62,6 +63,10 @@ public interface CacheableService<T> {
T unknownCustomKeyGenerator(Object arg1);
T customCacheManager(Object arg1);
T unknownCustomCacheManager(Object arg1);
T throwChecked(Object arg1) throws Exception;
T throwUnchecked(Object arg1);

View File

@@ -28,6 +28,7 @@ import org.springframework.cache.annotation.Caching;
*
* @author Costin Leau
* @author Phillip Webb
* @author Stephane Nicoll
*/
public class DefaultCacheableService implements CacheableService<Long> {
@@ -121,6 +122,18 @@ public class DefaultCacheableService implements CacheableService<Long> {
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", cacheManager = "customCacheManager")
public Long customCacheManager(Object arg1) {
return counter.getAndIncrement();
}
@Override
@Cacheable(value = "default", cacheManager = "unknownBeanName")
public Long unknownCustomCacheManager(Object arg1) {
return counter.getAndIncrement();
}
@Override
@CachePut("default")
public Long update(Object arg1) {

View File

@@ -40,6 +40,7 @@ import org.springframework.context.annotation.Configuration;
* Integration tests for @EnableCaching and its related @Configuration classes.
*
* @author Chris Beams
* @author Stephane Nicoll
*/
public class EnableCachingTests extends AbstractAnnotationTests {
@@ -145,6 +146,13 @@ public class EnableCachingTests extends AbstractAnnotationTests {
public KeyGenerator customKeyGenerator() {
return new SomeCustomKeyGenerator();
}
@Bean
public CacheManager customCacheManager() {
SimpleCacheManager cm = new SimpleCacheManager();
cm.setCaches(Arrays.asList(new ConcurrentMapCache("default")));
return cm;
}
}