diff --git a/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java b/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java index 915f07f152..91fcfac66b 100644 --- a/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java +++ b/spring-context/src/main/java/org/springframework/cache/annotation/SpringCacheAnnotationParser.java @@ -59,30 +59,48 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria } protected Collection parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) { + Collection ops = parseCacheAnnotations(cachingConfig, ae, false); + if (ops != null && ops.size() > 1 && ae.getAnnotations().length > 0) { + // More than one operation found -> local declarations override interface-declared ones... + Collection localOps = parseCacheAnnotations(cachingConfig, ae, true); + if (localOps != null) { + return localOps; + } + } + return ops; + } + + private Collection parseCacheAnnotations( + DefaultCacheConfig cachingConfig, AnnotatedElement ae, boolean localOnly) { + Collection ops = null; - Collection cacheables = AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class); + Collection cacheables = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class) : + AnnotatedElementUtils.findAllMergedAnnotations(ae, Cacheable.class)); if (!cacheables.isEmpty()) { ops = lazyInit(ops); for (Cacheable cacheable : cacheables) { ops.add(parseCacheableAnnotation(ae, cachingConfig, cacheable)); } } - Collection evicts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class); + Collection evicts = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class) : + AnnotatedElementUtils.findAllMergedAnnotations(ae, CacheEvict.class)); if (!evicts.isEmpty()) { ops = lazyInit(ops); for (CacheEvict evict : evicts) { ops.add(parseEvictAnnotation(ae, cachingConfig, evict)); } } - Collection puts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class); + Collection puts = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class) : + AnnotatedElementUtils.findAllMergedAnnotations(ae, CachePut.class)); if (!puts.isEmpty()) { ops = lazyInit(ops); for (CachePut put : puts) { ops.add(parsePutAnnotation(ae, cachingConfig, put)); } } - Collection cachings = AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class); + Collection cachings = (localOnly ? AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class) : + AnnotatedElementUtils.findAllMergedAnnotations(ae, Caching.class)); if (!cachings.isEmpty()) { ops = lazyInit(ops); for (Caching caching : cachings) { @@ -193,7 +211,7 @@ public class SpringCacheAnnotationParser implements CacheAnnotationParser, Seria * @return the default config (never {@code null}) */ DefaultCacheConfig getDefaultCacheConfig(Class target) { - CacheConfig annotation = AnnotatedElementUtils.getMergedAnnotation(target, CacheConfig.class); + CacheConfig annotation = AnnotatedElementUtils.findMergedAnnotation(target, CacheConfig.class); if (annotation != null) { return new DefaultCacheConfig(annotation.cacheNames(), annotation.keyGenerator(), annotation.cacheManager(), annotation.cacheResolver()); diff --git a/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java b/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java index 24495bdb1d..27ef6f3c03 100644 --- a/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java +++ b/spring-context/src/test/java/org/springframework/cache/CacheReproTests.java @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -180,7 +179,7 @@ public class CacheReproTests { assertSame(tb, cache.get("tb1").get()); } - @Test @Ignore // TODO + @Test public void spr15271FindsOnInterfaceWithCglibProxy() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Spr15271ConfigB.class); Spr15271Interface bean = context.getBean(Spr15271Interface.class); diff --git a/spring-context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTests.java b/spring-context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTests.java index b9d9baff49..52bb3d2e3b 100644 --- a/spring-context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTests.java +++ b/spring-context/src/test/java/org/springframework/cache/annotation/AnnotationCacheOperationSourceTests.java @@ -246,8 +246,7 @@ public class AnnotationCacheOperationSourceTests { @Test public void cacheConfigFromInterface() { - assertNull(getOps(InterfaceCacheConfig.class, "interfaceCacheConfig")); - Collection ops = getOps(CacheConfigIfc.class, "interfaceCacheConfig"); + Collection ops = getOps(InterfaceCacheConfig.class, "interfaceCacheConfig"); CacheOperation cacheOperation = ops.iterator().next(); assertSharedConfig(cacheOperation, "", "", "", "myCache"); }