Avoid synthesizable check for common annotation types
This revision considers any java/javax and org.springframework.lang annotations as not synthesizable upfront, checking not only in isSynthesizable but also at synthesizeAnnotation(Array) level. Issue: SPR-16933
This commit is contained in:
parent
f8340838b3
commit
6cd9060183
|
|
@ -1226,7 +1226,7 @@ public abstract class AnnotatedElementUtils {
|
||||||
if (AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
|
if (AnnotationUtils.isInJavaLangAnnotationPackage(currentAnnotationType)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (currentAnnotationType == Nullable.class || currentAnnotationType.getName().startsWith("java")) {
|
if (AnnotationUtils.hasPlainJavaAnnotationsOnly(currentAnnotationType)) {
|
||||||
// @Nullable and standard Java annotations are only meant to have standard Java meta-annotations
|
// @Nullable and standard Java annotations are only meant to have standard Java meta-annotations
|
||||||
// -> not worth searching otherwise.
|
// -> not worth searching otherwise.
|
||||||
return ((annotationType != null && annotationType.getName().startsWith("java")) ||
|
return ((annotationType != null && annotationType.getName().startsWith("java")) ||
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import java.lang.reflect.AnnotatedElement;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
|
|
@ -918,6 +919,29 @@ public abstract class AnnotationUtils {
|
||||||
return metaPresent;
|
return metaPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the {@link Annotation} with the supplied name is defined in the
|
||||||
|
* {@code java.lang.annotation} or {@code org.springframework.lang} package.
|
||||||
|
* @param annotatedElement the potential annotation type to check
|
||||||
|
* @return {@code true} if the annotation is in the {@code java.lang.annotation}
|
||||||
|
* or {@code org.springframework.lang} package
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
static boolean hasPlainJavaAnnotationsOnly(@Nullable Object annotatedElement) {
|
||||||
|
Class<?> clazz;
|
||||||
|
if (annotatedElement instanceof Class) {
|
||||||
|
clazz = (Class<?>) annotatedElement;
|
||||||
|
}
|
||||||
|
else if (annotatedElement instanceof Member) {
|
||||||
|
clazz = ((Member) annotatedElement).getDeclaringClass();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String name = clazz.getName();
|
||||||
|
return (name.startsWith("java") || name.startsWith("org.springframework.lang."));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the supplied {@link Annotation} is defined in the core JDK
|
* Determine if the supplied {@link Annotation} is defined in the core JDK
|
||||||
* {@code java.lang.annotation} package.
|
* {@code java.lang.annotation} package.
|
||||||
|
|
@ -1509,7 +1533,7 @@ public abstract class AnnotationUtils {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) {
|
static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) {
|
||||||
if (annotation instanceof SynthesizedAnnotation) {
|
if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) {
|
||||||
return annotation;
|
return annotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1585,7 +1609,7 @@ public abstract class AnnotationUtils {
|
||||||
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
|
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
|
||||||
*/
|
*/
|
||||||
public static <A extends Annotation> A synthesizeAnnotation(Class<A> annotationType) {
|
public static <A extends Annotation> A synthesizeAnnotation(Class<A> annotationType) {
|
||||||
return synthesizeAnnotation(Collections.<String, Object> emptyMap(), annotationType, null);
|
return synthesizeAnnotation(Collections.emptyMap(), annotationType, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1604,8 +1628,10 @@ public abstract class AnnotationUtils {
|
||||||
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
|
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
|
||||||
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
|
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
|
||||||
*/
|
*/
|
||||||
static Annotation[] synthesizeAnnotationArray(
|
static Annotation[] synthesizeAnnotationArray(Annotation[] annotations, @Nullable Object annotatedElement) {
|
||||||
Annotation[] annotations, @Nullable Object annotatedElement) {
|
if (hasPlainJavaAnnotationsOnly(annotatedElement)) {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
Annotation[] synthesized = (Annotation[]) Array.newInstance(
|
Annotation[] synthesized = (Annotation[]) Array.newInstance(
|
||||||
annotations.getClass().getComponentType(), annotations.length);
|
annotations.getClass().getComponentType(), annotations.length);
|
||||||
|
|
@ -1634,7 +1660,9 @@ public abstract class AnnotationUtils {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Nullable
|
@Nullable
|
||||||
static <A extends Annotation> A[] synthesizeAnnotationArray(@Nullable Map<String, Object>[] maps, Class<A> annotationType) {
|
static <A extends Annotation> A[] synthesizeAnnotationArray(
|
||||||
|
@Nullable Map<String, Object>[] maps, Class<A> annotationType) {
|
||||||
|
|
||||||
if (maps == null) {
|
if (maps == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -1716,6 +1744,10 @@ public abstract class AnnotationUtils {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static boolean isSynthesizable(Class<? extends Annotation> annotationType) {
|
private static boolean isSynthesizable(Class<? extends Annotation> annotationType) {
|
||||||
|
if (hasPlainJavaAnnotationsOnly(annotationType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Boolean synthesizable = synthesizableCache.get(annotationType);
|
Boolean synthesizable = synthesizableCache.get(annotationType);
|
||||||
if (synthesizable != null) {
|
if (synthesizable != null) {
|
||||||
return synthesizable;
|
return synthesizable;
|
||||||
|
|
@ -1764,7 +1796,7 @@ public abstract class AnnotationUtils {
|
||||||
*/
|
*/
|
||||||
static List<String> getAttributeAliasNames(Method attribute) {
|
static List<String> getAttributeAliasNames(Method attribute) {
|
||||||
AliasDescriptor descriptor = AliasDescriptor.from(attribute);
|
AliasDescriptor descriptor = AliasDescriptor.from(attribute);
|
||||||
return (descriptor != null ? descriptor.getAttributeAliasNames() : Collections.<String> emptyList());
|
return (descriptor != null ? descriptor.getAttributeAliasNames() : Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -64,7 +64,7 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib
|
||||||
public void visitEnd() {
|
public void visitEnd() {
|
||||||
super.visitEnd();
|
super.visitEnd();
|
||||||
|
|
||||||
Class<?> annotationClass = this.attributes.annotationType();
|
Class<? extends Annotation> annotationClass = this.attributes.annotationType();
|
||||||
if (annotationClass != null) {
|
if (annotationClass != null) {
|
||||||
List<AnnotationAttributes> attributeList = this.attributesMap.get(this.annotationType);
|
List<AnnotationAttributes> attributeList = this.attributesMap.get(this.annotationType);
|
||||||
if (attributeList == null) {
|
if (attributeList == null) {
|
||||||
|
|
@ -73,20 +73,22 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib
|
||||||
else {
|
else {
|
||||||
attributeList.add(0, this.attributes);
|
attributeList.add(0, this.attributes);
|
||||||
}
|
}
|
||||||
Set<Annotation> visited = new LinkedHashSet<>();
|
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationClass.getName())) {
|
||||||
Annotation[] metaAnnotations = AnnotationUtils.getAnnotations(annotationClass);
|
Set<Annotation> visited = new LinkedHashSet<>();
|
||||||
if (!ObjectUtils.isEmpty(metaAnnotations)) {
|
Annotation[] metaAnnotations = AnnotationUtils.getAnnotations(annotationClass);
|
||||||
for (Annotation metaAnnotation : metaAnnotations) {
|
if (!ObjectUtils.isEmpty(metaAnnotations)) {
|
||||||
if (!AnnotationUtils.isInJavaLangAnnotationPackage(metaAnnotation)) {
|
for (Annotation metaAnnotation : metaAnnotations) {
|
||||||
recursivelyCollectMetaAnnotations(visited, metaAnnotation);
|
if (!AnnotationUtils.isInJavaLangAnnotationPackage(metaAnnotation)) {
|
||||||
|
recursivelyCollectMetaAnnotations(visited, metaAnnotation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Set<String> metaAnnotationTypeNames = new LinkedHashSet<>(visited.size());
|
||||||
|
for (Annotation ann : visited) {
|
||||||
|
metaAnnotationTypeNames.add(ann.annotationType().getName());
|
||||||
|
}
|
||||||
|
this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
|
||||||
}
|
}
|
||||||
Set<String> metaAnnotationTypeNames = new LinkedHashSet<>(visited.size());
|
|
||||||
for (Annotation ann : visited) {
|
|
||||||
metaAnnotationTypeNames.add(ann.annotationType().getName());
|
|
||||||
}
|
|
||||||
this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue