提交 50e980c0 编写于 作者: J Juergen Hoeller

Validate declared annotations before deciding between reflection and ASM

Issue: SPR-16564
上级 1b1a69a1
......@@ -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;
......@@ -55,6 +56,7 @@ import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
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;
......@@ -659,8 +661,11 @@ class ConfigurationClassParser {
return new SourceClass(Object.class);
}
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) {
......
......@@ -60,10 +60,9 @@ import org.springframework.util.MultiValueMap;
* individual method for details on which search algorithm is used.
*
* <p><strong>Get semantics</strong> are limited to searching for annotations
* that are either <em>present</em> on an {@code AnnotatedElement} (i.e.,
* declared locally or {@linkplain java.lang.annotation.Inherited inherited})
* or declared within the annotation hierarchy <em>above</em> the
* {@code AnnotatedElement}.
* that are either <em>present</em> on an {@code AnnotatedElement} (i.e. declared
* locally or {@linkplain java.lang.annotation.Inherited inherited}) or declared
* within the annotation hierarchy <em>above</em> the {@code AnnotatedElement}.
*
* <p><strong>Find semantics</strong> are much more exhaustive, providing
* <em>get semantics</em> plus support for the following:
......@@ -77,14 +76,13 @@ import org.springframework.util.MultiValueMap;
* </ul>
*
* <h3>Support for {@code @Inherited}</h3>
* <p>Methods following <em>get semantics</em> 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
* <em>find semantics</em> will completely ignore the presence of
* {@code @Inherited} since the <em>find</em> search algorithm manually
* traverses type and method hierarchies and thereby implicitly supports
* annotation inheritance without the need for {@code @Inherited}.
* <p>Methods following <em>get semantics</em> 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 <em>find semantics</em>
* will completely ignore the presence of {@code @Inherited} since the <em>find</em>
* 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
......@@ -794,7 +792,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})
*/
@Nullable
private static <T> T searchWithGetSemantics(AnnotatedElement element,
......@@ -815,7 +813,7 @@ public class AnnotatedElementUtils {
* @param containerType the type of the container that holds repeatable
* annotations, or {@code null} if the annotation is not repeatable
* @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})
* @since 4.3
*/
@Nullable
......@@ -848,7 +846,7 @@ public class AnnotatedElementUtils {
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor, potentially {@code null}
* @return the result of the processor (potentially {@code null})
*/
@Nullable
private static <T> T searchWithGetSemantics(AnnotatedElement element,
......@@ -909,7 +907,7 @@ public class AnnotatedElementUtils {
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor, potentially {@code null}
* @return the result of the processor (potentially {@code null})
* @since 4.2
*/
@Nullable
......@@ -979,7 +977,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})
* @since 4.2
*/
@Nullable
......@@ -1001,7 +999,7 @@ public class AnnotatedElementUtils {
* @param containerType the type of the container that holds repeatable
* annotations, or {@code null} if the annotation is not repeatable
* @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})
* @since 4.3
*/
@Nullable
......@@ -1039,7 +1037,7 @@ public class AnnotatedElementUtils {
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor, potentially {@code null}
* @return the result of the processor (potentially {@code null})
* @since 4.2
*/
@Nullable
......
......@@ -898,6 +898,31 @@ public abstract class AnnotationUtils {
return (annotationType != null && annotationType.startsWith("java.lang.annotation"));
}
/**
* Check the declared attributes of the given annotation, in particular covering
* Google App Engine's late arrival of {@code TypeNotPresentExceptionProxy} for
* {@code Class} values (instead of early {@code Class.getAnnotations() failure}.
* <p>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())) {
if (method.getReturnType() == 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.
......@@ -1835,13 +1860,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);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册