+ update aspectj cache aspects
+ update integration tests
This commit is contained in:
parent
1e2f49104d
commit
d10f2258e8
|
@ -18,7 +18,9 @@ package org.springframework.cache.aspectj;
|
|||
|
||||
import org.springframework.cache.annotation.AnnotationCacheOperationSource;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* Concrete AspectJ cache aspect using Spring's @{@link Cacheable} annotation.
|
||||
|
@ -59,6 +61,20 @@ public aspect AnnotationCacheAspect extends AbstractCacheAspect {
|
|||
private pointcut executionOfAnyPublicMethodInAtCacheEvictType() :
|
||||
execution(public * ((@CacheEvict *)+).*(..)) && @this(CacheEvict);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link CachePut}
|
||||
* annotation, or any subtype of a type with the {@code CachePut} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCachePutType() :
|
||||
execution(public * ((@CachePut *)+).*(..)) && @this(CachePut);
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the @{@link Caching}
|
||||
* annotation, or any subtype of a type with the {@code Caching} annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtCachingType() :
|
||||
execution(public * ((@Caching *)+).*(..)) && @this(Caching);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link Cacheable} annotation.
|
||||
*/
|
||||
|
@ -71,6 +87,18 @@ public aspect AnnotationCacheAspect extends AbstractCacheAspect {
|
|||
private pointcut executionOfCacheEvictMethod() :
|
||||
execution(* *(..)) && @annotation(CacheEvict);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link CachePut} annotation.
|
||||
*/
|
||||
private pointcut executionOfCachePutMethod() :
|
||||
execution(* *(..)) && @annotation(CachePut);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the @{@link Caching} annotation.
|
||||
*/
|
||||
private pointcut executionOfCachingMethod() :
|
||||
execution(* *(..)) && @annotation(Caching);
|
||||
|
||||
/**
|
||||
* Definition of pointcut from super aspect - matched join points will have Spring
|
||||
* cache management applied.
|
||||
|
@ -78,8 +106,11 @@ public aspect AnnotationCacheAspect extends AbstractCacheAspect {
|
|||
protected pointcut cacheMethodExecution(Object cachedObject) :
|
||||
(executionOfAnyPublicMethodInAtCacheableType()
|
||||
|| executionOfAnyPublicMethodInAtCacheEvictType()
|
||||
|| executionOfAnyPublicMethodInAtCachePutType()
|
||||
|| executionOfAnyPublicMethodInAtCachingType()
|
||||
|| executionOfCacheableMethod()
|
||||
|| executionOfCacheEvictMethod())
|
||||
|| executionOfCacheEvictMethod()
|
||||
|| executionOfCachePutMethod()
|
||||
|| executionOfCachingMethod())
|
||||
&& this(cachedObject);
|
||||
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2010 the original author or authors.
|
||||
* 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.
|
||||
|
@ -18,38 +18,48 @@ package org.springframework.cache.aspectj;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.config.AnnotatedClassCacheableService;
|
||||
import org.springframework.cache.config.CacheableService;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* Abstract annotation test (containing several reusable methods).
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public abstract class AbstractAnnotationTest {
|
||||
|
||||
protected ApplicationContext ctx;
|
||||
|
||||
protected CacheableService cs;
|
||||
protected CacheableService<?> cs;
|
||||
|
||||
protected CacheableService ccs;
|
||||
protected CacheableService<?> ccs;
|
||||
|
||||
protected abstract String getConfig();
|
||||
protected CacheManager cm;
|
||||
|
||||
/** @return a refreshed application context */
|
||||
protected abstract ApplicationContext getApplicationContext();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ctx = new ClassPathXmlApplicationContext(getConfig());
|
||||
ctx = getApplicationContext();
|
||||
cs = ctx.getBean("service", CacheableService.class);
|
||||
ccs = ctx.getBean("classService", CacheableService.class);
|
||||
cm = ctx.getBean(CacheManager.class);
|
||||
Collection<String> cn = cm.getCacheNames();
|
||||
assertTrue(cn.contains("default"));
|
||||
}
|
||||
|
||||
public void testCacheable(CacheableService service) throws Exception {
|
||||
public void testCacheable(CacheableService<?> service) throws Exception {
|
||||
Object o1 = new Object();
|
||||
Object o2 = new Object();
|
||||
|
||||
Object r1 = service.cache(o1);
|
||||
Object r2 = service.cache(o1);
|
||||
|
@ -59,9 +69,8 @@ public abstract class AbstractAnnotationTest {
|
|||
assertSame(r1, r3);
|
||||
}
|
||||
|
||||
public void testInvalidate(CacheableService service) throws Exception {
|
||||
public void testEvict(CacheableService<?> service) throws Exception {
|
||||
Object o1 = new Object();
|
||||
Object o2 = new Object();
|
||||
|
||||
Object r1 = service.cache(o1);
|
||||
Object r2 = service.cache(o1);
|
||||
|
@ -74,7 +83,98 @@ public abstract class AbstractAnnotationTest {
|
|||
assertSame(r3, r4);
|
||||
}
|
||||
|
||||
public void testConditionalExpression(CacheableService service) throws Exception {
|
||||
public void testEvictEarly(CacheableService<?> service) throws Exception {
|
||||
Object o1 = new Object();
|
||||
|
||||
Object r1 = service.cache(o1);
|
||||
Object r2 = service.cache(o1);
|
||||
|
||||
assertSame(r1, r2);
|
||||
try {
|
||||
service.evictEarly(o1);
|
||||
} catch (RuntimeException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
Object r3 = service.cache(o1);
|
||||
Object r4 = service.cache(o1);
|
||||
assertNotSame(r1, r3);
|
||||
assertSame(r3, r4);
|
||||
}
|
||||
|
||||
public void testEvictException(CacheableService<?> service) throws Exception {
|
||||
Object o1 = new Object();
|
||||
|
||||
Object r1 = service.cache(o1);
|
||||
Object r2 = service.cache(o1);
|
||||
|
||||
assertSame(r1, r2);
|
||||
try {
|
||||
service.evictWithException(o1);
|
||||
} catch (RuntimeException ex) {
|
||||
// expected
|
||||
}
|
||||
// exception occurred, eviction skipped, data should still be in the cache
|
||||
Object r3 = service.cache(o1);
|
||||
assertSame(r1, r3);
|
||||
}
|
||||
|
||||
public void testEvictWKey(CacheableService<?> service) throws Exception {
|
||||
Object o1 = new Object();
|
||||
|
||||
Object r1 = service.cache(o1);
|
||||
Object r2 = service.cache(o1);
|
||||
|
||||
assertSame(r1, r2);
|
||||
service.evict(o1, null);
|
||||
Object r3 = service.cache(o1);
|
||||
Object r4 = service.cache(o1);
|
||||
assertNotSame(r1, r3);
|
||||
assertSame(r3, r4);
|
||||
}
|
||||
|
||||
public void testEvictWKeyEarly(CacheableService<?> service) throws Exception {
|
||||
Object o1 = new Object();
|
||||
|
||||
Object r1 = service.cache(o1);
|
||||
Object r2 = service.cache(o1);
|
||||
|
||||
assertSame(r1, r2);
|
||||
|
||||
try {
|
||||
service.invalidateEarly(o1, null);
|
||||
} catch (Exception ex) {
|
||||
// expected
|
||||
}
|
||||
Object r3 = service.cache(o1);
|
||||
Object r4 = service.cache(o1);
|
||||
assertNotSame(r1, r3);
|
||||
assertSame(r3, r4);
|
||||
}
|
||||
|
||||
public void testEvictAll(CacheableService<?> service) throws Exception {
|
||||
Object o1 = new Object();
|
||||
|
||||
Object r1 = service.cache(o1);
|
||||
Object r2 = service.cache(o1);
|
||||
|
||||
Object o2 = new Object();
|
||||
Object r10 = service.cache(o2);
|
||||
|
||||
assertSame(r1, r2);
|
||||
assertNotSame(r1, r10);
|
||||
service.evictAll(new Object());
|
||||
Cache cache = cm.getCache("default");
|
||||
assertNull(cache.get(o1));
|
||||
assertNull(cache.get(o2));
|
||||
|
||||
Object r3 = service.cache(o1);
|
||||
Object r4 = service.cache(o1);
|
||||
assertNotSame(r1, r3);
|
||||
assertSame(r3, r4);
|
||||
}
|
||||
|
||||
public void testConditionalExpression(CacheableService<?> service) throws Exception {
|
||||
Object r1 = service.conditional(4);
|
||||
Object r2 = service.conditional(4);
|
||||
|
||||
|
@ -86,7 +186,7 @@ public abstract class AbstractAnnotationTest {
|
|||
assertSame(r3, r4);
|
||||
}
|
||||
|
||||
public void testKeyExpression(CacheableService service) throws Exception {
|
||||
public void testKeyExpression(CacheableService<?> service) throws Exception {
|
||||
Object r1 = service.key(5, 1);
|
||||
Object r2 = service.key(5, 2);
|
||||
|
||||
|
@ -98,7 +198,26 @@ public abstract class AbstractAnnotationTest {
|
|||
assertNotSame(r3, r4);
|
||||
}
|
||||
|
||||
public void testCheckedThrowable(CacheableService service) throws Exception {
|
||||
public void testNullValue(CacheableService<?> service) throws Exception {
|
||||
Object key = new Object();
|
||||
assertNull(service.nullValue(key));
|
||||
int nr = service.nullInvocations().intValue();
|
||||
assertNull(service.nullValue(key));
|
||||
assertEquals(nr, service.nullInvocations().intValue());
|
||||
assertNull(service.nullValue(new Object()));
|
||||
assertEquals(nr + 1, service.nullInvocations().intValue());
|
||||
}
|
||||
|
||||
public void testMethodName(CacheableService<?> service, String keyName) throws Exception {
|
||||
Object key = new Object();
|
||||
Object r1 = service.name(key);
|
||||
assertSame(r1, service.name(key));
|
||||
Cache cache = cm.getCache("default");
|
||||
// assert the method name is used
|
||||
assertNotNull(cache.get(keyName));
|
||||
}
|
||||
|
||||
public void testCheckedThrowable(CacheableService<?> service) throws Exception {
|
||||
String arg = UUID.randomUUID().toString();
|
||||
try {
|
||||
service.throwChecked(arg);
|
||||
|
@ -108,16 +227,165 @@ public abstract class AbstractAnnotationTest {
|
|||
}
|
||||
}
|
||||
|
||||
public void testUncheckedThrowable(CacheableService service) throws Exception {
|
||||
public void testUncheckedThrowable(CacheableService<?> service) throws Exception {
|
||||
try {
|
||||
service.throwUnchecked(Long.valueOf(1));
|
||||
fail("Excepted exception");
|
||||
} catch (RuntimeException ex) {
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
assertTrue("Excepted different exception type and got " + ex.getClass(),
|
||||
ex instanceof UnsupportedOperationException);
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testNullArg(CacheableService<?> service) {
|
||||
Object r1 = service.cache(null);
|
||||
assertSame(r1, service.cache(null));
|
||||
}
|
||||
|
||||
public void testCacheUpdate(CacheableService<?> service) {
|
||||
Object o = new Object();
|
||||
Cache cache = cm.getCache("default");
|
||||
assertNull(cache.get(o));
|
||||
Object r1 = service.update(o);
|
||||
assertSame(r1, cache.get(o).get());
|
||||
|
||||
o = new Object();
|
||||
assertNull(cache.get(o));
|
||||
Object r2 = service.update(o);
|
||||
assertSame(r2, cache.get(o).get());
|
||||
}
|
||||
|
||||
public void testConditionalCacheUpdate(CacheableService<?> service) {
|
||||
Integer one = Integer.valueOf(1);
|
||||
Integer three = Integer.valueOf(3);
|
||||
|
||||
Cache cache = cm.getCache("default");
|
||||
assertEquals(one, Integer.valueOf(service.conditionalUpdate(one).toString()));
|
||||
assertNull(cache.get(one));
|
||||
|
||||
assertEquals(three, Integer.valueOf(service.conditionalUpdate(three).toString()));
|
||||
assertEquals(three, Integer.valueOf(cache.get(three).get().toString()));
|
||||
}
|
||||
|
||||
public void testMultiCache(CacheableService<?> service) {
|
||||
Object o1 = new Object();
|
||||
Object o2 = new Object();
|
||||
|
||||
Cache primary = cm.getCache("primary");
|
||||
Cache secondary = cm.getCache("secondary");
|
||||
|
||||
assertNull(primary.get(o1));
|
||||
assertNull(secondary.get(o1));
|
||||
Object r1 = service.multiCache(o1);
|
||||
assertSame(r1, primary.get(o1).get());
|
||||
assertSame(r1, secondary.get(o1).get());
|
||||
|
||||
Object r2 = service.multiCache(o1);
|
||||
Object r3 = service.multiCache(o1);
|
||||
|
||||
assertSame(r1, r2);
|
||||
assertSame(r1, r3);
|
||||
|
||||
assertNull(primary.get(o2));
|
||||
assertNull(secondary.get(o2));
|
||||
Object r4 = service.multiCache(o2);
|
||||
assertSame(r4, primary.get(o2).get());
|
||||
assertSame(r4, secondary.get(o2).get());
|
||||
}
|
||||
|
||||
public void testMultiEvict(CacheableService<?> service) {
|
||||
Object o1 = new Object();
|
||||
|
||||
Object r1 = service.multiCache(o1);
|
||||
Object r2 = service.multiCache(o1);
|
||||
|
||||
Cache primary = cm.getCache("primary");
|
||||
Cache secondary = cm.getCache("secondary");
|
||||
|
||||
assertSame(r1, r2);
|
||||
assertSame(r1, primary.get(o1).get());
|
||||
assertSame(r1, secondary.get(o1).get());
|
||||
|
||||
service.multiEvict(o1);
|
||||
assertNull(primary.get(o1));
|
||||
assertNull(secondary.get(o1));
|
||||
|
||||
Object r3 = service.multiCache(o1);
|
||||
Object r4 = service.multiCache(o1);
|
||||
assertNotSame(r1, r3);
|
||||
assertSame(r3, r4);
|
||||
|
||||
assertSame(r3, primary.get(o1).get());
|
||||
assertSame(r4, secondary.get(o1).get());
|
||||
}
|
||||
|
||||
public void testMultiPut(CacheableService<?> service) {
|
||||
Object o = Integer.valueOf(1);
|
||||
|
||||
Cache primary = cm.getCache("primary");
|
||||
Cache secondary = cm.getCache("secondary");
|
||||
|
||||
assertNull(primary.get(o));
|
||||
assertNull(secondary.get(o));
|
||||
Object r1 = service.multiUpdate(o);
|
||||
assertSame(r1, primary.get(o).get());
|
||||
assertSame(r1, secondary.get(o).get());
|
||||
|
||||
o = Integer.valueOf(2);
|
||||
assertNull(primary.get(o));
|
||||
assertNull(secondary.get(o));
|
||||
Object r2 = service.multiUpdate(o);
|
||||
assertSame(r2, primary.get(o).get());
|
||||
assertSame(r2, secondary.get(o).get());
|
||||
}
|
||||
|
||||
public void testMultiCacheAndEvict(CacheableService<?> service) {
|
||||
String methodName = "multiCacheAndEvict";
|
||||
|
||||
Cache primary = cm.getCache("primary");
|
||||
Cache secondary = cm.getCache("secondary");
|
||||
Object key = Integer.valueOf(1);
|
||||
|
||||
secondary.put(key, key);
|
||||
|
||||
assertNull(secondary.get(methodName));
|
||||
assertSame(key, secondary.get(key).get());
|
||||
|
||||
Object r1 = service.multiCacheAndEvict(key);
|
||||
assertSame(r1, service.multiCacheAndEvict(key));
|
||||
|
||||
// assert the method name is used
|
||||
assertSame(r1, primary.get(methodName).get());
|
||||
assertNull(secondary.get(methodName));
|
||||
assertNull(secondary.get(key));
|
||||
}
|
||||
|
||||
public void testMultiConditionalCacheAndEvict(CacheableService<?> service) {
|
||||
Cache primary = cm.getCache("primary");
|
||||
Cache secondary = cm.getCache("secondary");
|
||||
Object key = Integer.valueOf(1);
|
||||
|
||||
secondary.put(key, key);
|
||||
|
||||
assertNull(primary.get(key));
|
||||
assertSame(key, secondary.get(key).get());
|
||||
|
||||
Object r1 = service.multiConditionalCacheAndEvict(key);
|
||||
Object r3 = service.multiConditionalCacheAndEvict(key);
|
||||
|
||||
assertTrue(!r1.equals(r3));
|
||||
assertNull(primary.get(key));
|
||||
|
||||
Object key2 = Integer.valueOf(3);
|
||||
Object r2 = service.multiConditionalCacheAndEvict(key2);
|
||||
assertSame(r2, service.multiConditionalCacheAndEvict(key2));
|
||||
|
||||
// assert the method name is used
|
||||
assertSame(r2, primary.get(key2).get());
|
||||
assertNull(secondary.get(key2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheable() throws Exception {
|
||||
testCacheable(cs);
|
||||
|
@ -125,7 +393,32 @@ public abstract class AbstractAnnotationTest {
|
|||
|
||||
@Test
|
||||
public void testInvalidate() throws Exception {
|
||||
testInvalidate(cs);
|
||||
testEvict(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEarlyInvalidate() throws Exception {
|
||||
testEvictEarly(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEvictWithException() throws Exception {
|
||||
testEvictException(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEvictAll() throws Exception {
|
||||
testEvictAll(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidateWithKey() throws Exception {
|
||||
testEvictWKey(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEarlyInvalidateWithKey() throws Exception {
|
||||
testEvictWKeyEarly(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -145,7 +438,70 @@ public abstract class AbstractAnnotationTest {
|
|||
|
||||
@Test
|
||||
public void testClassCacheInvalidate() throws Exception {
|
||||
testInvalidate(ccs);
|
||||
testEvict(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassEarlyInvalidate() throws Exception {
|
||||
testEvictEarly(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassEvictAll() throws Exception {
|
||||
testEvictAll(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassEvictWithException() throws Exception {
|
||||
testEvictException(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassCacheInvalidateWKey() throws Exception {
|
||||
testEvictWKey(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassEarlyInvalidateWithKey() throws Exception {
|
||||
testEvictWKeyEarly(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullValue() throws Exception {
|
||||
testNullValue(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassNullValue() throws Exception {
|
||||
Object key = new Object();
|
||||
assertNull(ccs.nullValue(key));
|
||||
int nr = ccs.nullInvocations().intValue();
|
||||
assertNull(ccs.nullValue(key));
|
||||
assertEquals(nr, ccs.nullInvocations().intValue());
|
||||
assertNull(ccs.nullValue(new Object()));
|
||||
// the check method is also cached
|
||||
assertEquals(nr, ccs.nullInvocations().intValue());
|
||||
assertEquals(nr + 1, AnnotatedClassCacheableService.nullInvocations.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodName() throws Exception {
|
||||
testMethodName(cs, "name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassMethodName() throws Exception {
|
||||
testMethodName(ccs, "namedefault");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullArg() throws Exception {
|
||||
testNullArg(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassNullArg() throws Exception {
|
||||
testNullArg(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -168,4 +524,73 @@ public abstract class AbstractAnnotationTest {
|
|||
testUncheckedThrowable(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
testCacheUpdate(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassUpdate() {
|
||||
testCacheUpdate(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalUpdate() {
|
||||
testConditionalCacheUpdate(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassConditionalUpdate() {
|
||||
testConditionalCacheUpdate(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiCache() {
|
||||
testMultiCache(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassMultiCache() {
|
||||
testMultiCache(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiEvict() {
|
||||
testMultiEvict(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassMultiEvict() {
|
||||
testMultiEvict(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiPut() {
|
||||
testMultiPut(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassMultiPut() {
|
||||
testMultiPut(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiCacheAndEvict() {
|
||||
testMultiCacheAndEvict(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassMultiCacheAndEvict() {
|
||||
testMultiCacheAndEvict(ccs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiConditionalCacheAndEvict() {
|
||||
testMultiConditionalCacheAndEvict(cs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassMultiConditionalCacheAndEvict() {
|
||||
testMultiConditionalCacheAndEvict(ccs);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2010 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.aspectj;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class AspectJAnnotationTest extends AbstractAnnotationTest {
|
||||
|
||||
|
||||
@Override
|
||||
protected ApplicationContext getApplicationContext() {
|
||||
return new GenericXmlApplicationContext("/org/springframework/cache/config/annotation-cache-aspectj.xml");
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2010 the original author or authors.
|
||||
* 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.
|
||||
|
@ -19,15 +19,18 @@ package org.springframework.cache.config;
|
|||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@Cacheable("default")
|
||||
public class AnnotatedClassCacheableService implements CacheableService {
|
||||
public class AnnotatedClassCacheableService implements CacheableService<Object> {
|
||||
|
||||
private AtomicLong counter = new AtomicLong();
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
public static final AtomicLong nullInvocations = new AtomicLong();
|
||||
|
||||
public Object cache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
|
@ -41,11 +44,63 @@ public class AnnotatedClassCacheableService implements CacheableService {
|
|||
public void invalidate(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void evictWithException(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should NOT occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", allEntries = true)
|
||||
public void evictAll(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", afterInvocation = false)
|
||||
public void evictEarly(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0")
|
||||
public void evict(Object arg1, Object arg2) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0", afterInvocation = false)
|
||||
public void invalidateEarly(Object arg1, Object arg2) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#p0")
|
||||
public Object key(Object arg1, Object arg2) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.caches[0].name")
|
||||
public Object name(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target")
|
||||
public Object rootVars(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut("default")
|
||||
public Object update(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut(value = "default", condition = "#arg.equals(3)")
|
||||
public Object conditionalUpdate(Object arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
public Object nullValue(Object arg1) {
|
||||
nullInvocations.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Number nullInvocations() {
|
||||
return nullInvocations.get();
|
||||
}
|
||||
|
||||
public Long throwChecked(Object arg1) throws Exception {
|
||||
throw new UnsupportedOperationException(arg1.toString());
|
||||
}
|
||||
|
@ -53,4 +108,31 @@ public class AnnotatedClassCacheableService implements CacheableService {
|
|||
public Long throwUnchecked(Object arg1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
// multi annotations
|
||||
|
||||
@Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") })
|
||||
public Object multiCache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
|
||||
public Object multiEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") })
|
||||
public Object multiCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
|
||||
public Object multiConditionalCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(put = { @CachePut("primary"), @CachePut("secondary") })
|
||||
public Object multiUpdate(Object arg1) {
|
||||
return arg1;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2010 the original author or authors.
|
||||
* 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.
|
||||
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.cache.config;
|
||||
|
||||
|
||||
/**
|
||||
* Basic service interface.
|
||||
*
|
||||
|
@ -28,11 +27,44 @@ public interface CacheableService<T> {
|
|||
|
||||
void invalidate(Object arg1);
|
||||
|
||||
void evictEarly(Object arg1);
|
||||
|
||||
void evictAll(Object arg1);
|
||||
|
||||
void evictWithException(Object arg1);
|
||||
|
||||
void evict(Object arg1, Object arg2);
|
||||
|
||||
void invalidateEarly(Object arg1, Object arg2);
|
||||
|
||||
T conditional(int field);
|
||||
|
||||
T key(Object arg1, Object arg2);
|
||||
|
||||
T name(Object arg1);
|
||||
|
||||
T nullValue(Object arg1);
|
||||
|
||||
T update(Object arg1);
|
||||
|
||||
T conditionalUpdate(Object arg2);
|
||||
|
||||
Number nullInvocations();
|
||||
|
||||
T rootVars(Object arg1);
|
||||
|
||||
T throwChecked(Object arg1) throws Exception;
|
||||
|
||||
T throwUnchecked(Object arg1);
|
||||
|
||||
// multi annotations
|
||||
T multiCache(Object arg1);
|
||||
|
||||
T multiEvict(Object arg1);
|
||||
|
||||
T multiCacheAndEvict(Object arg1);
|
||||
|
||||
T multiConditionalCacheAndEvict(Object arg1);
|
||||
|
||||
T multiUpdate(Object arg1);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2010 the original author or authors.
|
||||
* 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.
|
||||
|
@ -19,8 +19,9 @@ package org.springframework.cache.config;
|
|||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
|
||||
/**
|
||||
* Simple cacheable service
|
||||
|
@ -29,7 +30,8 @@ import org.springframework.cache.annotation.Cacheable;
|
|||
*/
|
||||
public class DefaultCacheableService implements CacheableService<Long> {
|
||||
|
||||
private AtomicLong counter = new AtomicLong();
|
||||
private final AtomicLong counter = new AtomicLong();
|
||||
private final AtomicLong nullInvocations = new AtomicLong();
|
||||
|
||||
@Cacheable("default")
|
||||
public Long cache(Object arg1) {
|
||||
|
@ -40,6 +42,29 @@ public class DefaultCacheableService implements CacheableService<Long> {
|
|||
public void invalidate(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict("default")
|
||||
public void evictWithException(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should NOT occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", allEntries = true)
|
||||
public void evictAll(Object arg1) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", afterInvocation = false)
|
||||
public void evictEarly(Object arg1) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0")
|
||||
public void evict(Object arg1, Object arg2) {
|
||||
}
|
||||
|
||||
@CacheEvict(value = "default", key = "#p0", afterInvocation = false)
|
||||
public void invalidateEarly(Object arg1, Object arg2) {
|
||||
throw new RuntimeException("exception thrown - evict should still occur");
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", condition = "#classField == 3")
|
||||
public Long conditional(int classField) {
|
||||
return counter.getAndIncrement();
|
||||
|
@ -50,6 +75,36 @@ public class DefaultCacheableService implements CacheableService<Long> {
|
|||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName")
|
||||
public Long name(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Cacheable(value = "default", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target")
|
||||
public Long rootVars(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut("default")
|
||||
public Long update(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@CachePut(value = "default", condition = "#arg.equals(3)")
|
||||
public Long conditionalUpdate(Object arg) {
|
||||
return Long.valueOf(arg.toString());
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long nullValue(Object arg1) {
|
||||
nullInvocations.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Number nullInvocations() {
|
||||
return nullInvocations.get();
|
||||
}
|
||||
|
||||
@Cacheable("default")
|
||||
public Long throwChecked(Object arg1) throws Exception {
|
||||
throw new Exception(arg1.toString());
|
||||
|
@ -59,4 +114,31 @@ public class DefaultCacheableService implements CacheableService<Long> {
|
|||
public Long throwUnchecked(Object arg1) {
|
||||
throw new UnsupportedOperationException(arg1.toString());
|
||||
}
|
||||
|
||||
// multi annotations
|
||||
|
||||
@Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") })
|
||||
public Long multiCache(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
|
||||
public Long multiEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") })
|
||||
public Long multiCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(cacheable = { @Cacheable(value = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") })
|
||||
public Long multiConditionalCacheAndEvict(Object arg1) {
|
||||
return counter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Caching(put = { @CachePut("primary"), @CachePut("secondary") })
|
||||
public Long multiUpdate(Object arg1) {
|
||||
return Long.valueOf(arg1.toString());
|
||||
}
|
||||
}
|
|
@ -13,13 +13,15 @@
|
|||
|
||||
<bean id="cacheAspect" class="org.springframework.cache.aspectj.AnnotationCacheAspect" factory-method="aspectOf">
|
||||
<property name="cacheManager" ref="cacheManager"/>
|
||||
<property name="cacheOperationSource" ref="annotationSource"/>
|
||||
<property name="cacheOperationSources" ref="annotationSource"/>
|
||||
</bean>
|
||||
|
||||
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
|
||||
<property name="caches">
|
||||
<set>
|
||||
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default"/>
|
||||
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="primary"/>
|
||||
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="secondary"/>
|
||||
</set>
|
||||
</property>
|
||||
</bean>
|
||||
|
|
Loading…
Reference in New Issue