diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index d10fb2bb29..b6af650b19 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -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. @@ -18,6 +18,7 @@ package org.springframework.context.annotation; import java.io.FileNotFoundException; import java.io.IOException; +import java.lang.annotation.Annotation; import java.net.UnknownHostException; import java.util.ArrayDeque; import java.util.ArrayList; @@ -53,6 +54,7 @@ import org.springframework.context.annotation.ConfigurationCondition.Configurati import org.springframework.core.NestedIOException; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; @@ -656,8 +658,11 @@ class ConfigurationClassParser { */ SourceClass asSourceClass(Class> classType) throws IOException { try { - // Sanity test that we can read annotations, if not fall back to ASM - classType.getAnnotations(); + // Sanity test that we can reflectively read annotations, + // including Class attributes; if not -> fall back to ASM + for (Annotation ann : classType.getAnnotations()) { + AnnotationUtils.validateAnnotation(ann); + } return new SourceClass(classType); } catch (Throwable ex) { diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java index d83747fee8..01fec3f0d4 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java @@ -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. @@ -59,10 +59,9 @@ import org.springframework.util.MultiValueMap; * individual method for details on which search algorithm is used. * *
Get semantics are limited to searching for annotations - * that are either present on an {@code AnnotatedElement} (i.e., - * declared locally or {@linkplain java.lang.annotation.Inherited inherited}) - * or declared within the annotation hierarchy above the - * {@code AnnotatedElement}. + * that are either present on an {@code AnnotatedElement} (i.e. declared + * locally or {@linkplain java.lang.annotation.Inherited inherited}) or declared + * within the annotation hierarchy above the {@code AnnotatedElement}. * *
Find semantics are much more exhaustive, providing * get semantics plus support for the following: @@ -76,14 +75,13 @@ import org.springframework.util.MultiValueMap; * * *
Methods following get semantics will honor the contract of - * Java's {@link java.lang.annotation.Inherited @Inherited} annotation except - * that locally declared annotations (including custom composed annotations) - * will be favored over inherited annotations. In contrast, methods following - * find semantics will completely ignore the presence of - * {@code @Inherited} since the find search algorithm manually - * traverses type and method hierarchies and thereby implicitly supports - * annotation inheritance without the need for {@code @Inherited}. + *
Methods following get semantics will honor the contract of Java's
+ * {@link java.lang.annotation.Inherited @Inherited} annotation except that locally
+ * declared annotations (including custom composed annotations) will be favored over
+ * inherited annotations. In contrast, methods following find semantics
+ * will completely ignore the presence of {@code @Inherited} since the find
+ * search algorithm manually traverses type and method hierarchies and thereby
+ * implicitly supports annotation inheritance without a need for {@code @Inherited}.
*
* @author Phillip Webb
* @author Juergen Hoeller
@@ -873,7 +871,7 @@ public class AnnotatedElementUtils {
* @param annotationName the fully qualified class name of the annotation
* type to find (as an alternative to {@code annotationType})
* @param processor the processor to delegate to
- * @return the result of the processor, potentially {@code null}
+ * @return the result of the processor (potentially {@code null})
*/
private static This method not failing indicates that {@link #getAnnotationAttributes(Annotation)}
+ * won't failure either (when attempted later on).
+ * @param annotation the annotation to validate
+ * @throws IllegalStateException if a declared {@code Class} attribute could not be read
+ * @since 4.3.15
+ * @see Class#getAnnotations()
+ * @see #getAnnotationAttributes(Annotation)
+ */
+ public static void validateAnnotation(Annotation annotation) {
+ for (Method method : getAttributeMethods(annotation.annotationType())) {
+ Class> returnType = method.getReturnType();
+ if (returnType == Class.class || returnType == Class[].class) {
+ try {
+ method.invoke(annotation);
+ }
+ catch (Throwable ex) {
+ throw new IllegalStateException("Could not obtain annotation attribute value for " + method, ex);
+ }
+ }
+ }
+ }
+
/**
* Retrieve the given annotation's attributes as a {@link Map}, preserving all
* attribute types.
@@ -1882,13 +1908,13 @@ public abstract class AnnotationUtils {
if (element instanceof Class && Annotation.class.isAssignableFrom((Class>) element)) {
// Meta-annotation or (default) value lookup on an annotation type
if (loggerToUse.isDebugEnabled()) {
- loggerToUse.debug("Failed to meta-introspect annotation [" + element + "]: " + ex);
+ loggerToUse.debug("Failed to meta-introspect annotation " + element + ": " + ex);
}
}
else {
// Direct annotation lookup on regular Class, Method, Field
if (loggerToUse.isInfoEnabled()) {
- loggerToUse.info("Failed to introspect annotations on [" + element + "]: " + ex);
+ loggerToUse.info("Failed to introspect annotations on " + element + ": " + ex);
}
}
}