Consistent non-exposure of inherited annotations in AnnotationMetadata

Closes gh-22766
This commit is contained in:
Juergen Hoeller 2019-04-08 15:59:06 +02:00
parent 2e7ed915cd
commit fd8fa301a6
3 changed files with 29 additions and 10 deletions

View File

@ -638,13 +638,13 @@ class ConfigurationClassParser {
* Factory method to obtain a {@link SourceClass} from a {@link Class}. * Factory method to obtain a {@link SourceClass} from a {@link Class}.
*/ */
SourceClass asSourceClass(@Nullable Class<?> classType) throws IOException { SourceClass asSourceClass(@Nullable Class<?> classType) throws IOException {
if (classType == null || classType.getName().startsWith("java.lang.annotation")) { if (classType == null || classType.getName().startsWith("java.lang.annotation.")) {
return this.objectSourceClass; return this.objectSourceClass;
} }
try { try {
// Sanity test that we can reflectively read annotations, // Sanity test that we can reflectively read annotations,
// including Class attributes; if not -> fall back to ASM // including Class attributes; if not -> fall back to ASM
for (Annotation ann : classType.getAnnotations()) { for (Annotation ann : classType.getDeclaredAnnotations()) {
AnnotationUtils.validateAnnotation(ann); AnnotationUtils.validateAnnotation(ann);
} }
return new SourceClass(classType); return new SourceClass(classType);
@ -670,7 +670,7 @@ class ConfigurationClassParser {
* Factory method to obtain a {@link SourceClass} from a class name. * Factory method to obtain a {@link SourceClass} from a class name.
*/ */
SourceClass asSourceClass(@Nullable String className) throws IOException { SourceClass asSourceClass(@Nullable String className) throws IOException {
if (className == null || className.startsWith("java.lang.annotation")) { if (className == null || className.startsWith("java.lang.annotation.")) {
return this.objectSourceClass; return this.objectSourceClass;
} }
if (className.startsWith("java")) { if (className.startsWith("java")) {
@ -1017,7 +1017,7 @@ class ConfigurationClassParser {
Set<SourceClass> result = new LinkedHashSet<>(); Set<SourceClass> result = new LinkedHashSet<>();
if (this.source instanceof Class) { if (this.source instanceof Class) {
Class<?> sourceClass = (Class<?>) this.source; Class<?> sourceClass = (Class<?>) this.source;
for (Annotation ann : sourceClass.getAnnotations()) { for (Annotation ann : sourceClass.getDeclaredAnnotations()) {
Class<?> annType = ann.annotationType(); Class<?> annType = ann.annotationType();
if (!annType.getName().startsWith("java")) { if (!annType.getName().startsWith("java")) {
try { try {

View File

@ -68,7 +68,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
*/ */
public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) { public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
super(introspectedClass); super(introspectedClass);
this.annotations = introspectedClass.getAnnotations(); this.annotations = introspectedClass.getDeclaredAnnotations();
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap; this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
} }

View File

@ -20,6 +20,7 @@ import java.io.Serializable;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
@ -52,7 +53,7 @@ import static org.junit.Assert.*;
public class AnnotationMetadataTests { public class AnnotationMetadataTests {
@Test @Test
public void standardAnnotationMetadata() throws Exception { public void standardAnnotationMetadata() {
AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponent.class, true); AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponent.class, true);
doTestAnnotationInfo(metadata); doTestAnnotationInfo(metadata);
doTestMethodAnnotationInfo(metadata); doTestMethodAnnotationInfo(metadata);
@ -68,7 +69,7 @@ public class AnnotationMetadataTests {
} }
@Test @Test
public void standardAnnotationMetadataForSubclass() throws Exception { public void standardAnnotationMetadataForSubclass() {
AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponentSubClass.class, true); AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponentSubClass.class, true);
doTestSubClassAnnotationInfo(metadata); doTestSubClassAnnotationInfo(metadata);
} }
@ -104,7 +105,7 @@ public class AnnotationMetadataTests {
} }
@Test @Test
public void standardAnnotationMetadataForInterface() throws Exception { public void standardAnnotationMetadataForInterface() {
AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotationMetadata.class, true); AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotationMetadata.class, true);
doTestMetadataForInterfaceClass(metadata); doTestMetadataForInterfaceClass(metadata);
} }
@ -132,7 +133,7 @@ public class AnnotationMetadataTests {
} }
@Test @Test
public void standardAnnotationMetadataForAnnotation() throws Exception { public void standardAnnotationMetadataForAnnotation() {
AnnotationMetadata metadata = new StandardAnnotationMetadata(Component.class, true); AnnotationMetadata metadata = new StandardAnnotationMetadata(Component.class, true);
doTestMetadataForAnnotationClass(metadata); doTestMetadataForAnnotationClass(metadata);
} }
@ -172,7 +173,7 @@ public class AnnotationMetadataTests {
* 'true' as is done in the main test above. * 'true' as is done in the main test above.
*/ */
@Test @Test
public void standardAnnotationMetadata_nestedAnnotationsAsMap_false() throws Exception { public void standardAnnotationMetadata_nestedAnnotationsAsMap_false() {
AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponent.class); AnnotationMetadata metadata = new StandardAnnotationMetadata(AnnotatedComponent.class);
AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName()); AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(SpecialAttr.class.getName());
Annotation[] nestedAnnoArray = (Annotation[]) specialAttrs.get("nestedAnnoArray"); Annotation[] nestedAnnoArray = (Annotation[]) specialAttrs.get("nestedAnnoArray");
@ -233,6 +234,20 @@ public class AnnotationMetadataTests {
assertMultipleAnnotationsWithIdenticalAttributeNames(metadata); assertMultipleAnnotationsWithIdenticalAttributeNames(metadata);
} }
@Test
public void inheritedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata() {
AnnotationMetadata metadata = new StandardAnnotationMetadata(NamedComposedAnnotationExtended.class);
assertFalse(metadata.hasAnnotation(NamedComposedAnnotation.class.getName()));
}
@Test
public void inheritedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingAnnotationMetadataReadingVisitor() throws Exception {
MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(NamedComposedAnnotationExtended.class.getName());
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
assertFalse(metadata.hasAnnotation(NamedComposedAnnotation.class.getName()));
}
private void assertMultipleAnnotationsWithIdenticalAttributeNames(AnnotationMetadata metadata) { private void assertMultipleAnnotationsWithIdenticalAttributeNames(AnnotationMetadata metadata) {
AnnotationAttributes attributes1 = (AnnotationAttributes) metadata.getAnnotationAttributes( AnnotationAttributes attributes1 = (AnnotationAttributes) metadata.getAnnotationAttributes(
@ -545,6 +560,7 @@ public class AnnotationMetadataTests {
@NamedAnnotation3(name = "name 3") @NamedAnnotation3(name = "name 3")
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)
@Inherited
public @interface NamedComposedAnnotation { public @interface NamedComposedAnnotation {
} }
@ -552,4 +568,7 @@ public class AnnotationMetadataTests {
public static class NamedComposedAnnotationClass { public static class NamedComposedAnnotationClass {
} }
public static class NamedComposedAnnotationExtended extends NamedComposedAnnotationClass {
}
} }