Honor contract of @Repeatable in AnnotationUtils

This commit introduces a minor bug fix for getRepeatableAnnotations()
so that it fully complies with the contract of Java's
getAnnotationsByType() method with regard to repeatable annotations
declared on multiple superclasses.

Issue: SPR-13068
This commit is contained in:
Sam Brannen 2015-06-20 16:53:46 +02:00
parent de9f27872e
commit 594c330205
2 changed files with 30 additions and 0 deletions

View File

@ -305,6 +305,13 @@ public abstract class AnnotationUtils {
return annotations;
}
if (annotatedElement instanceof Class) {
Class<?> superclass = ((Class<?>) annotatedElement).getSuperclass();
if ((superclass != null) && (Object.class != superclass)) {
return getRepeatableAnnotations(superclass, annotationType, containerAnnotationType);
}
}
return getRepeatableAnnotations(annotatedElement, annotationType, containerAnnotationType, false);
}

View File

@ -586,6 +586,25 @@ public class AnnotationUtilsTests {
assertThat(values, is(expectedValuesSpring));
}
@Test
public void getRepeatableAnnotationsDeclaredOnMultipleSuperclasses() {
final Class<?> clazz = SubSubMyRepeatableWithAdditionalLocalDeclarationsClass.class;
final List<String> expectedValuesJava = Arrays.asList("X", "Y", "Z");
final List<String> expectedValuesSpring = Arrays.asList("X", "Y", "Z", "meta2");
// Java 8
MyRepeatable[] array = clazz.getAnnotationsByType(MyRepeatable.class);
assertNotNull(array);
List<String> values = stream(array).map(MyRepeatable::value).collect(toList());
assertThat(values, is(expectedValuesJava));
// Spring
Set<MyRepeatable> set = getRepeatableAnnotations(clazz, MyRepeatable.class, MyRepeatableContainer.class);
assertNotNull(set);
values = set.stream().map(MyRepeatable::value).collect(toList());
assertThat(values, is(expectedValuesSpring));
}
@Test
public void getDeclaredRepeatableAnnotationsDeclaredOnClass() {
final List<String> expectedValuesJava = Arrays.asList("A", "B", "C");
@ -1358,6 +1377,10 @@ public class AnnotationUtilsTests {
static class SubMyRepeatableWithAdditionalLocalDeclarationsClass extends MyRepeatableClass {
}
static class SubSubMyRepeatableWithAdditionalLocalDeclarationsClass extends
SubMyRepeatableWithAdditionalLocalDeclarationsClass {
}
enum RequestMethod {
GET, POST
}