Find annotations on implemented generic superclass methods as well
Includes Java 8 getDeclaredAnnotation shortcut for lookup on Class. Issue: SPR-17146
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
@@ -525,19 +525,11 @@ public class AnnotatedElementUtilsTests {
|
||||
assertNotNull("Should find @Transactional on ConcreteClassWithInheritedAnnotation.handle() method", attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>{@code AbstractClassWithInheritedAnnotation} declares {@code handleParameterized(T)}; whereas,
|
||||
* {@code ConcreteClassWithInheritedAnnotation} declares {@code handleParameterized(String)}.
|
||||
* <p>As of Spring 4.2, {@code AnnotatedElementUtils.processWithFindSemantics()} does not resolve an
|
||||
* <em>equivalent</em> method in {@code AbstractClassWithInheritedAnnotation} for the <em>bridged</em>
|
||||
* {@code handleParameterized(String)} method.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Test
|
||||
public void findMergedAnnotationAttributesInheritedFromBridgedMethod() throws NoSuchMethodException {
|
||||
Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handleParameterized", String.class);
|
||||
AnnotationAttributes attributes = findMergedAnnotationAttributes(method, Transactional.class);
|
||||
assertNull("Should not find @Transactional on bridged ConcreteClassWithInheritedAnnotation.handleParameterized()", attributes);
|
||||
assertNotNull("Should find @Transactional on bridged ConcreteClassWithInheritedAnnotation.handleParameterized()", attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -546,7 +538,7 @@ public class AnnotatedElementUtilsTests {
|
||||
* @since 4.2
|
||||
*/
|
||||
@Test
|
||||
public void findMergedAnnotationAttributesFromBridgeMethod() throws NoSuchMethodException {
|
||||
public void findMergedAnnotationAttributesFromBridgeMethod() {
|
||||
Method[] methods = StringGenericParameter.class.getMethods();
|
||||
Method bridgeMethod = null;
|
||||
Method bridgedMethod = null;
|
||||
@@ -733,6 +725,20 @@ public class AnnotatedElementUtilsTests {
|
||||
assertEquals(1, allMergedAnnotations.size());
|
||||
}
|
||||
|
||||
@Test // SPR-16060
|
||||
public void findMethodAnnotationFromGenericInterface() throws Exception {
|
||||
Method method = ImplementsInterfaceWithGenericAnnotatedMethod.class.getMethod("foo", String.class);
|
||||
Order order = findMergedAnnotation(method, Order.class);
|
||||
assertNotNull(order);
|
||||
}
|
||||
|
||||
@Test // SPR-17146
|
||||
public void findMethodAnnotationFromGenericSuperclass() throws Exception {
|
||||
Method method = ExtendsBaseClassWithGenericAnnotatedMethod.class.getMethod("foo", String.class);
|
||||
Order order = findMergedAnnotation(method, Order.class);
|
||||
assertNotNull(order);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -167,9 +167,7 @@ public class AnnotationUtilsTests {
|
||||
|
||||
assertNull(bridgedMethod.getAnnotation(Order.class));
|
||||
assertNull(getAnnotation(bridgedMethod, Order.class));
|
||||
// AnnotationUtils.findAnnotation(Method, Class<A>) will not find an annotation on
|
||||
// the bridge method for a bridged method.
|
||||
assertNull(findAnnotation(bridgedMethod, Order.class));
|
||||
assertNotNull(findAnnotation(bridgedMethod, Order.class));
|
||||
|
||||
assertNotNull(bridgedMethod.getAnnotation(Transactional.class));
|
||||
assertNotNull(getAnnotation(bridgedMethod, Transactional.class));
|
||||
@@ -190,6 +188,13 @@ public class AnnotationUtilsTests {
|
||||
assertNotNull(order);
|
||||
}
|
||||
|
||||
@Test // SPR-17146
|
||||
public void findMethodAnnotationFromGenericSuperclass() throws Exception {
|
||||
Method method = ExtendsBaseClassWithGenericAnnotatedMethod.class.getMethod("foo", String.class);
|
||||
Order order = findAnnotation(method, Order.class);
|
||||
assertNotNull(order);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findMethodAnnotationFromInterfaceOnSuper() throws Exception {
|
||||
Method method = SubOfImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
|
||||
@@ -204,7 +209,7 @@ public class AnnotationUtilsTests {
|
||||
assertNotNull(order);
|
||||
}
|
||||
|
||||
/** @since 4.1.2 */
|
||||
// @since 4.1.2
|
||||
@Test
|
||||
public void findClassAnnotationFavorsMoreLocallyDeclaredComposedAnnotationsOverAnnotationsOnInterfaces() {
|
||||
Component component = findAnnotation(ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class, Component.class);
|
||||
@@ -212,7 +217,7 @@ public class AnnotationUtilsTests {
|
||||
assertEquals("meta2", component.value());
|
||||
}
|
||||
|
||||
/** @since 4.0.3 */
|
||||
// @since 4.0.3
|
||||
@Test
|
||||
public void findClassAnnotationFavorsMoreLocallyDeclaredComposedAnnotationsOverInheritedAnnotations() {
|
||||
Transactional transactional = findAnnotation(SubSubClassWithInheritedAnnotation.class, Transactional.class);
|
||||
@@ -220,7 +225,7 @@ public class AnnotationUtilsTests {
|
||||
assertTrue("readOnly flag for SubSubClassWithInheritedAnnotation", transactional.readOnly());
|
||||
}
|
||||
|
||||
/** @since 4.0.3 */
|
||||
// @since 4.0.3
|
||||
@Test
|
||||
public void findClassAnnotationFavorsMoreLocallyDeclaredComposedAnnotationsOverInheritedComposedAnnotations() {
|
||||
Component component = findAnnotation(SubSubClassWithInheritedMetaAnnotation.class, Component.class);
|
||||
@@ -1762,18 +1767,6 @@ public class AnnotationUtilsTests {
|
||||
public static class SubTransactionalAndOrderedClass extends TransactionalAndOrderedClass {
|
||||
}
|
||||
|
||||
public interface InterfaceWithGenericAnnotatedMethod<T> {
|
||||
|
||||
@Order
|
||||
void foo(T t);
|
||||
}
|
||||
|
||||
public static class ImplementsInterfaceWithGenericAnnotatedMethod implements InterfaceWithGenericAnnotatedMethod<String> {
|
||||
|
||||
public void foo(String t) {
|
||||
}
|
||||
}
|
||||
|
||||
public interface InterfaceWithAnnotatedMethod {
|
||||
|
||||
@Order
|
||||
@@ -1806,6 +1799,30 @@ public class AnnotationUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
public interface InterfaceWithGenericAnnotatedMethod<T> {
|
||||
|
||||
@Order
|
||||
void foo(T t);
|
||||
}
|
||||
|
||||
public static class ImplementsInterfaceWithGenericAnnotatedMethod implements InterfaceWithGenericAnnotatedMethod<String> {
|
||||
|
||||
public void foo(String t) {
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class BaseClassWithGenericAnnotatedMethod<T> {
|
||||
|
||||
@Order
|
||||
abstract void foo(T t);
|
||||
}
|
||||
|
||||
public static class ExtendsBaseClassWithGenericAnnotatedMethod extends BaseClassWithGenericAnnotatedMethod<String> {
|
||||
|
||||
public void foo(String t) {
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@interface MyRepeatableContainer {
|
||||
|
||||
Reference in New Issue
Block a user