Skip to content

Commit

Permalink
Support @inherited again in reflection-based AnnotationMetadata
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sbrannen committed Nov 28, 2019
1 parent 85016ae commit 7cedffc
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 33 deletions.
Expand Up @@ -85,7 +85,7 @@ public StandardAnnotationMetadata(Class<?> introspectedClass) {
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;
}
Expand Down
Expand Up @@ -42,7 +42,7 @@

/**
* 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
Expand All @@ -51,9 +51,6 @@
*/
class AnnotationMetadataTests {

private static final boolean reproduceGh24077 = false;


@Test
void standardAnnotationMetadata() {
AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotatedComponent.class);
Expand All @@ -73,18 +70,18 @@ void asmAnnotationMetadata() throws Exception {
@Test
void standardAnnotationMetadataForSubclass() {
AnnotationMetadata metadata = AnnotationMetadata.introspect(AnnotatedComponentSubClass.class);
doTestSubClassAnnotationInfo(metadata);
doTestSubClassAnnotationInfo(metadata, false);
}

@Test
void asmAnnotationMetadataForSubclass() throws Exception {
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();
Expand All @@ -97,16 +94,16 @@ private void doTestSubClassAnnotationInfo(AnnotationMetadata metadata) {
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();
Expand Down Expand Up @@ -252,7 +249,7 @@ void composedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingAnnota
@Test
void inheritedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata() {
AnnotationMetadata metadata = AnnotationMetadata.introspect(NamedComposedAnnotationExtended.class);
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isFalse();
assertThat(metadata.hasAnnotation(NamedComposedAnnotation.class.getName())).isTrue();
}

@Test
Expand Down Expand Up @@ -294,29 +291,18 @@ private void doTestAnnotationInfo(AnnotationMetadata metadata) {

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);
Expand Down Expand Up @@ -513,6 +499,7 @@ public enum SubclassEnum {
@DirectAnnotation(value = "direct", additional = "", additionalArray = {})
@MetaMetaAnnotation
@EnumSubclasses({SubclassEnum.FOO, SubclassEnum.BAR})
@NamedComposedAnnotation
private static class AnnotatedComponent implements Serializable {

@TestAutowired
Expand Down

0 comments on commit 7cedffc

Please sign in to comment.