Support @Inherited again in reflection-based AnnotationMetadata

Spring Framework 5.2 introduced a regression in reflection-based
AnnotationMetadata. Specifically, as of 5.2, StandardAnnotationMetadata
no longer found @Inherited annotations from superclasses.

This commit fixes this regression by switching to the INHERITED_ANNOTATIONS
SearchStrategy when creating the MergedAnnotations used within
StandardAnnotationMetadata,

Note, however, that the discrepancy between StandardAnnotationMetadata
and SimpleAnnotationMetadata (i.e., reflection-based vs. ASM-based)
regarding @Inherited support still remains as it was prior to Spring
Framework 5.2.

Closes gh-24077
This commit is contained in:
Sam Brannen 2019-11-29 00:07:44 +01:00
parent 85016aef30
commit 7cedffc707
2 changed files with 20 additions and 33 deletions

View File

@ -85,7 +85,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
super(introspectedClass);
this.mergedAnnotations = MergedAnnotations.from(introspectedClass,
SearchStrategy.DIRECT, RepeatableContainers.none(),
SearchStrategy.INHERITED_ANNOTATIONS, RepeatableContainers.none(),
AnnotationFilter.NONE);
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
}

View File

@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Unit tests demonstrating that the reflection-based {@link StandardAnnotationMetadata}
* and ASM-based {@code AnnotationMetadataReadingVisitor} produce identical output.
* and ASM-based {@code SimpleAnnotationMetadata} produce <em>almost</em> identical output.
*
* @author Juergen Hoeller
* @author Chris Beams
@ -51,9 +51,6 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
class AnnotationMetadataTests {
private static final boolean reproduceGh24077 = false;
@Test
void standardAnnotationMetadata() {
AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotatedComponent.class);
@ -73,7 +70,7 @@ class AnnotationMetadataTests {
@Test
void standardAnnotationMetadataForSubclass() {
AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotatedComponentSubClass.class);
doTestSubClassAnnotationInfo(metadata);
doTestSubClassAnnotationInfo(metadata, false);
}
@Test
@ -81,10 +78,10 @@ class AnnotationMetadataTests {
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(AnnotatedComponentSubClass.class.getName());
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
doTestSubClassAnnotationInfo(metadata);
doTestSubClassAnnotationInfo(metadata, true);
}
private void doTestSubClassAnnotationInfo(AnnotationMetadata metadata) {
private void doTestSubClassAnnotationInfo(AnnotationMetadata metadata, boolean asm) {
assertThat(metadata.getClassName()).isEqualTo(AnnotatedComponentSubClass.class.getName());
assertThat(metadata.isInterface()).isFalse();
assertThat(metadata.isAnnotation()).isFalse();
@ -97,16 +94,16 @@ class AnnotationMetadataTests {
assertThat(metadata.isAnnotated(Scope.class.getName())).isFalse();
assertThat(metadata.isAnnotated(SpecialAttr.class.getName())).isFalse();
if (reproduceGh24077) {
assertThat(metadata.isAnnotated(NamedComposedAnnotation.class.getName())).isTrue();
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isTrue();
assertThat(metadata.getAnnotationTypes()).containsExactly(NamedComposedAnnotation.class.getName());
}
else {
if (asm) {
assertThat(metadata.isAnnotated(NamedComposedAnnotation.class.getName())).isFalse();
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isFalse();
assertThat(metadata.getAnnotationTypes()).isEmpty();
}
else {
assertThat(metadata.isAnnotated(NamedComposedAnnotation.class.getName())).isTrue();
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isTrue();
assertThat(metadata.getAnnotationTypes()).containsExactly(NamedComposedAnnotation.class.getName());
}
assertThat(metadata.hasAnnotation(Component.class.getName())).isFalse();
assertThat(metadata.hasAnnotation(Scope.class.getName())).isFalse();
@ -252,7 +249,7 @@ class AnnotationMetadataTests {
@Test
void inheritedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata() {
AnnotationMetadata metadata = AnnotationMetadata.introspect(NamedComposedAnnotationExtended.class);
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isFalse();
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isTrue();
}
@Test
@ -294,29 +291,18 @@ class AnnotationMetadataTests {
assertThat(metadata.isAnnotated(Component.class.getName())).isTrue();
if (reproduceGh24077) {
assertThat(metadata.isAnnotated(NamedComposedAnnotation.class.getName())).isTrue();
}
assertThat(metadata.isAnnotated(NamedComposedAnnotation.class.getName())).isTrue();
assertThat(metadata.hasAnnotation(Component.class.getName())).isTrue();
assertThat(metadata.hasAnnotation(Scope.class.getName())).isTrue();
assertThat(metadata.hasAnnotation(SpecialAttr.class.getName())).isTrue();
if (reproduceGh24077) {
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isTrue();
assertThat(metadata.getAnnotationTypes()).containsExactlyInAnyOrder(
Component.class.getName(), Scope.class.getName(),
SpecialAttr.class.getName(), DirectAnnotation.class.getName(),
MetaMetaAnnotation.class.getName(), EnumSubclasses.class.getName(),
NamedComposedAnnotation.class.getName());
}
else {
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isFalse();
assertThat(metadata.getAnnotationTypes()).containsExactlyInAnyOrder(
Component.class.getName(), Scope.class.getName(),
SpecialAttr.class.getName(), DirectAnnotation.class.getName(),
MetaMetaAnnotation.class.getName(), EnumSubclasses.class.getName());
}
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isTrue();
assertThat(metadata.getAnnotationTypes()).containsExactlyInAnyOrder(
Component.class.getName(), Scope.class.getName(),
SpecialAttr.class.getName(), DirectAnnotation.class.getName(),
MetaMetaAnnotation.class.getName(), EnumSubclasses.class.getName(),
NamedComposedAnnotation.class.getName());
AnnotationAttributes compAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(Component.class.getName());
assertThat(compAttrs).hasSize(1);
@ -513,6 +499,7 @@ class AnnotationMetadataTests {
@DirectAnnotation(value = "direct", additional = "", additionalArray = {})
@MetaMetaAnnotation
@EnumSubclasses({SubclassEnum.FOO, SubclassEnum.BAR})
@NamedComposedAnnotation
private static class AnnotatedComponent implements Serializable {
@TestAutowired