From 3cca57a801ac8b4867b8e6abda4baca39b06c6c3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 28 Oct 2016 23:32:55 +0200 Subject: [PATCH] Local merged annotation lookup in SpringCacheAnnotationParser Issue: SPR-14781 Issue: SPR-14801 (cherry picked from commit 08972ef) --- .../SpringCacheAnnotationParser.java | 8 +-- .../AnnotationCacheOperationSourceTests.java | 54 ++++++++++++++++--- 2 files changed, 51 insertions(+), 11 deletions(-) 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 d58bd1337fcc..3a024e0faa68 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 @@ -62,28 +62,28 @@ public Collection parseCacheAnnotations(Method method) { protected Collection parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) { Collection ops = null; - Collection cacheables = AnnotatedElementUtils.findAllMergedAnnotations(ae, Cacheable.class); + Collection cacheables = AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class); if (!cacheables.isEmpty()) { ops = lazyInit(ops); for (Cacheable cacheable : cacheables) { ops.add(parseCacheableAnnotation(ae, cachingConfig, cacheable)); } } - Collection evicts = AnnotatedElementUtils.findAllMergedAnnotations(ae, CacheEvict.class); + Collection evicts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class); if (!evicts.isEmpty()) { ops = lazyInit(ops); for (CacheEvict evict : evicts) { ops.add(parseEvictAnnotation(ae, cachingConfig, evict)); } } - Collection puts = AnnotatedElementUtils.findAllMergedAnnotations(ae, CachePut.class); + Collection puts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class); if (!puts.isEmpty()) { ops = lazyInit(ops); for (CachePut put : puts) { ops.add(parsePutAnnotation(ae, cachingConfig, put)); } } - Collection cachings = AnnotatedElementUtils.findAllMergedAnnotations(ae, Caching.class); + Collection cachings = AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class); if (!cachings.isEmpty()) { ops = lazyInit(ops); for (Caching caching : cachings) { 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 409d969213e0..b9d9baff495c 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 @@ -75,7 +75,7 @@ public void caching() throws Exception { @Test public void emptyCaching() throws Exception { - Collection ops = getOps(AnnotatedClass.class, "emptyCaching", 0); + getOps(AnnotatedClass.class, "emptyCaching", 0); } @Test @@ -155,7 +155,7 @@ public void customKeyGeneratorInherited() { @Test public void keyAndKeyGeneratorCannotBeSetTogether() { - exception.expect(IllegalStateException.class); + this.exception.expect(IllegalStateException.class); getOps(AnnotatedClass.class, "invalidKeyAndKeyGeneratorSet"); } @@ -189,7 +189,7 @@ public void customCacheResolverInherited() { @Test public void cacheResolverAndCacheManagerCannotBeSetTogether() { - exception.expect(IllegalStateException.class); + this.exception.expect(IllegalStateException.class); getOps(AnnotatedClass.class, "invalidCacheResolverAndCacheManagerSet"); } @@ -244,6 +244,22 @@ public void severalCacheConfigUseClosest() { assertSharedConfig(cacheOperation, "", "", "", "myCache"); } + @Test + public void cacheConfigFromInterface() { + assertNull(getOps(InterfaceCacheConfig.class, "interfaceCacheConfig")); + Collection ops = getOps(CacheConfigIfc.class, "interfaceCacheConfig"); + CacheOperation cacheOperation = ops.iterator().next(); + assertSharedConfig(cacheOperation, "", "", "", "myCache"); + } + + @Test + public void cacheAnnotationOverride() { + Collection ops = getOps(InterfaceCacheConfig.class, "interfaceCacheableOverride"); + assertSame(1, ops.size()); + CacheOperation cacheOperation = ops.iterator().next(); + assertTrue(cacheOperation instanceof CacheableOperation); + } + @Test public void partialClassLevelWithCustomCacheManager() { Collection ops = getOps(AnnotatedClassWithSomeDefault.class, "methodLevelCacheManager", 1); @@ -275,7 +291,7 @@ private Collection getOps(Class target, String name, int expe private Collection getOps(Class target, String name) { try { Method method = target.getMethod(name); - return source.getCacheOperations(method, target); + return this.source.getCacheOperations(method, target); } catch (NoSuchMethodException ex) { throw new IllegalStateException(ex); @@ -430,7 +446,7 @@ public void noCustomization() { @CacheConfigFoo - @CacheConfig(cacheNames = "myCache") // multiple sources + @CacheConfig(cacheNames = "myCache") // multiple sources private static class MultipleCacheConfig { @Cacheable @@ -439,6 +455,30 @@ public void multipleCacheConfig() { } + @CacheConfig(cacheNames = "myCache") + private interface CacheConfigIfc { + + @Cacheable + void interfaceCacheConfig(); + + @CachePut + void interfaceCacheableOverride(); + } + + + private static class InterfaceCacheConfig implements CacheConfigIfc { + + @Override + public void interfaceCacheConfig() { + } + + @Override + @Cacheable + public void interfaceCacheableOverride() { + } + } + + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Cacheable("foo") @@ -491,7 +531,7 @@ public void multipleCacheConfig() { @Retention(RetentionPolicy.RUNTIME) - @Target({ ElementType.METHOD, ElementType.TYPE }) + @Target({ElementType.METHOD, ElementType.TYPE}) @Cacheable(cacheNames = "shadowed cache name", key = "shadowed key") @interface ComposedCacheable { @@ -507,7 +547,7 @@ public void multipleCacheConfig() { @Retention(RetentionPolicy.RUNTIME) - @Target({ ElementType.METHOD, ElementType.TYPE }) + @Target({ElementType.METHOD, ElementType.TYPE}) @CacheEvict(cacheNames = "shadowed cache name", key = "shadowed key") @interface ComposedCacheEvict {