Nullability refinements and related polishing
Includes fix for typo in visitor class names. See gh-22909
This commit is contained in:
@@ -898,7 +898,7 @@ public abstract class AnnotationUtils {
|
||||
for (int i = 0; i < methods.size(); i++) {
|
||||
Method method = methods.get(i);
|
||||
Object defaultValue = method.getDefaultValue();
|
||||
if(defaultValue != null) {
|
||||
if (defaultValue != null) {
|
||||
result.put(method.getName(), new DefaultValueHolder(defaultValue));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
|
||||
private final AnnotationTypeMappings[] mappings;
|
||||
|
||||
|
||||
private MergedAnnotationsCollection(Collection<MergedAnnotation<?>> annotations) {
|
||||
Assert.notNull(annotations, "Annotations must not be null");
|
||||
this.annotations = annotations.toArray(new MergedAnnotation<?>[0]);
|
||||
@@ -52,11 +53,11 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
Assert.notNull(annotation, "Annotation must not be null");
|
||||
Assert.isTrue(annotation.isDirectlyPresent(), "Annotation must be directly present");
|
||||
Assert.isTrue(annotation.getAggregateIndex() == 0, "Annotation must have aggregate index of zero");
|
||||
this.mappings[i] = AnnotationTypeMappings.forAnnotationType(
|
||||
annotation.getType());
|
||||
this.mappings[i] = AnnotationTypeMappings.forAnnotationType(annotation.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterator<MergedAnnotation<Annotation>> iterator() {
|
||||
return Spliterators.iterator(spliterator());
|
||||
@@ -67,8 +68,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
return spliterator(null);
|
||||
}
|
||||
|
||||
private <A extends Annotation> Spliterator<MergedAnnotation<A>> spliterator(
|
||||
@Nullable Object annotationType) {
|
||||
private <A extends Annotation> Spliterator<MergedAnnotation<A>> spliterator(@Nullable Object annotationType) {
|
||||
return new AnnotationsSpliterator<>(annotationType);
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
|
||||
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
|
||||
@Nullable MergedAnnotationSelector<A> selector) {
|
||||
|
||||
MergedAnnotation<A> result = find(annotationType, predicate, selector);
|
||||
return (result != null ? result : MergedAnnotation.missing());
|
||||
}
|
||||
@@ -154,12 +155,15 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private <A extends Annotation> MergedAnnotation<A> find(Object requiredType,
|
||||
Predicate<? super MergedAnnotation<A>> predicate,
|
||||
MergedAnnotationSelector<A> selector) {
|
||||
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
|
||||
@Nullable MergedAnnotationSelector<A> selector) {
|
||||
|
||||
if (selector == null) {
|
||||
selector = MergedAnnotationSelectors.nearest();
|
||||
}
|
||||
|
||||
MergedAnnotation<A> result = null;
|
||||
for (int i = 0; i < this.annotations.length; i++) {
|
||||
MergedAnnotation<?> root = this.annotations[i];
|
||||
@@ -208,7 +212,7 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
|
||||
static MergedAnnotations of(Collection<MergedAnnotation<?>> annotations) {
|
||||
Assert.notNull(annotations, "Annotations must not be null");
|
||||
if(annotations.isEmpty()) {
|
||||
if (annotations.isEmpty()) {
|
||||
return TypeMappedAnnotations.NONE;
|
||||
}
|
||||
return new MergedAnnotationsCollection(annotations);
|
||||
@@ -242,7 +246,8 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
}
|
||||
}
|
||||
if (annotationResult != -1) {
|
||||
MergedAnnotation<A> mergedAnnotation = createMergedAnnotationIfPossible(annotationResult, this.mappingCursors[annotationResult]);
|
||||
MergedAnnotation<A> mergedAnnotation = createMergedAnnotationIfPossible(
|
||||
annotationResult, this.mappingCursors[annotationResult]);
|
||||
this.mappingCursors[annotationResult]++;
|
||||
if (mergedAnnotation == null) {
|
||||
return tryAdvance(action);
|
||||
@@ -275,20 +280,19 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
private MergedAnnotation<A> createMergedAnnotationIfPossible(
|
||||
int annotationIndex, int mappingIndex) {
|
||||
private MergedAnnotation<A> createMergedAnnotationIfPossible(int annotationIndex, int mappingIndex) {
|
||||
MergedAnnotation<?> root = annotations[annotationIndex];
|
||||
if(mappingIndex == 0) {
|
||||
if (mappingIndex == 0) {
|
||||
return (MergedAnnotation<A>) root;
|
||||
}
|
||||
IntrospectionFailureLogger logger = (this.requiredType != null
|
||||
? IntrospectionFailureLogger.INFO
|
||||
: IntrospectionFailureLogger.DEBUG);
|
||||
IntrospectionFailureLogger logger = (this.requiredType != null ?
|
||||
IntrospectionFailureLogger.INFO : IntrospectionFailureLogger.DEBUG);
|
||||
return TypeMappedAnnotation.createIfPossible(
|
||||
mappings[annotationIndex].get(mappingIndex), root, logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Spliterator<MergedAnnotation<A>> trySplit() {
|
||||
return null;
|
||||
}
|
||||
@@ -309,7 +313,6 @@ final class MergedAnnotationsCollection implements MergedAnnotations {
|
||||
public int characteristics() {
|
||||
return NONNULL | IMMUTABLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -71,8 +70,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnnotation<A> {
|
||||
|
||||
private static final Object[] EMPTY_OBJECT_ARRAY = {};
|
||||
|
||||
private static final Map<Class<?>, Object> EMPTY_ARRAYS;
|
||||
static {
|
||||
Map<Class<?>, Object> emptyArrays = new HashMap<>();
|
||||
@@ -386,7 +383,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
|
||||
return (attributeIndex != -1 ? getValue(attributeIndex, type) : null);
|
||||
}
|
||||
|
||||
private final Object getRequiredValue(int attributeIndex, String attributeName) {
|
||||
private Object getRequiredValue(int attributeIndex, String attributeName) {
|
||||
Object value = getValue(attributeIndex, Object.class);
|
||||
if (value == null) {
|
||||
throw new NoSuchElementException("No element at attribute index "
|
||||
@@ -527,7 +524,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
|
||||
(attributeType == String[].class && value instanceof Class[])) {
|
||||
return value;
|
||||
}
|
||||
if(attributeType.isArray() && isEmptyObjectArray(value)) {
|
||||
if (attributeType.isArray() && isEmptyObjectArray(value)) {
|
||||
return emptyArray(attributeType.getComponentType());
|
||||
}
|
||||
if (!attributeType.isInstance(value)) {
|
||||
@@ -540,7 +537,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
|
||||
}
|
||||
|
||||
private boolean isEmptyObjectArray(Object value) {
|
||||
return value instanceof Object[] && Arrays.equals((Object[]) value, EMPTY_OBJECT_ARRAY);
|
||||
return (value instanceof Object[] && ((Object[]) value).length == 0);
|
||||
}
|
||||
|
||||
private Object emptyArray(Class<?> componentType) {
|
||||
@@ -556,7 +553,8 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
|
||||
return (MergedAnnotation<?>) value;
|
||||
}
|
||||
AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0);
|
||||
return new TypeMappedAnnotation<>(mapping, null, this.source, value, getValueExtractor(value), this.aggregateIndex);
|
||||
return new TypeMappedAnnotation<>(
|
||||
mapping, null, this.source, value, getValueExtractor(value), this.aggregateIndex);
|
||||
}
|
||||
|
||||
private BiFunction<Method, Object, Object> getValueExtractor(Object value) {
|
||||
@@ -659,8 +657,8 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static <A extends Annotation> TypeMappedAnnotation<A> createIfPossible(
|
||||
AnnotationTypeMapping mapping, @Nullable Object source, Object rootAttribute,
|
||||
private static <A extends Annotation> TypeMappedAnnotation<A> createIfPossible(
|
||||
AnnotationTypeMapping mapping, @Nullable Object source, @Nullable Object rootAttribute,
|
||||
BiFunction<Method, Object, Object> valueExtractor,
|
||||
int aggregateIndex, IntrospectionFailureLogger logger) {
|
||||
|
||||
|
||||
@@ -51,8 +51,10 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
|
||||
private final boolean nestedAnnotationsAsMap;
|
||||
|
||||
@Nullable
|
||||
private Set<String> annotationTypes;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code StandardAnnotationMetadata} wrapper for the given Class.
|
||||
* @param introspectedClass the Class to introspect
|
||||
@@ -109,22 +111,20 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
@Nullable
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return AnnotationMetadata.super.getAnnotationAttributes(annotationName,
|
||||
classValuesAsString);
|
||||
return AnnotationMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getMergedAnnotationAttributes(
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return AnnotationMetadata.super.getAllAnnotationAttributes(annotationName,
|
||||
classValuesAsString);
|
||||
return AnnotationMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getAllAnnotationAttributes(
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -138,7 +138,7 @@ public class StandardMethodMetadata implements MethodMetadata {
|
||||
return MethodMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod,
|
||||
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
annotationName, classValuesAsString, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,7 +148,7 @@ public class StandardMethodMetadata implements MethodMetadata {
|
||||
return MethodMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod,
|
||||
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
annotationName, classValuesAsString, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
if (!visible) {
|
||||
return null;
|
||||
|
||||
@@ -118,6 +118,7 @@ class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
|
||||
// no-op
|
||||
return new EmptyAnnotationVisitor();
|
||||
|
||||
@@ -55,9 +55,10 @@ class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVis
|
||||
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<>(4);
|
||||
|
||||
public MergedAnnotationReadingVisitor(ClassLoader classLoader,
|
||||
@Nullable Object source, Class<A> annotationType,
|
||||
Consumer<MergedAnnotation<A>> consumer) {
|
||||
|
||||
public MergedAnnotationReadingVisitor(@Nullable ClassLoader classLoader, @Nullable Object source,
|
||||
Class<A> annotationType, Consumer<MergedAnnotation<A>> consumer) {
|
||||
|
||||
super(SpringAsmInfo.ASM_VERSION);
|
||||
this.classLoader = classLoader;
|
||||
this.source = source;
|
||||
@@ -65,6 +66,7 @@ class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVis
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visit(String name, Object value) {
|
||||
if (value instanceof Type) {
|
||||
@@ -79,9 +81,9 @@ class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVis
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
|
||||
return visitAnnotation(descriptor,
|
||||
annotation -> this.attributes.put(name, annotation));
|
||||
return visitAnnotation(descriptor, annotation -> this.attributes.put(name, annotation));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,61 +93,57 @@ class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVis
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
MergedAnnotation<A> annotation = MergedAnnotation.of(this.classLoader,
|
||||
this.source, this.annotationType, this.attributes);
|
||||
MergedAnnotation<A> annotation = MergedAnnotation.of(
|
||||
this.classLoader, this.source, this.annotationType, this.attributes);
|
||||
this.consumer.accept(annotation);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <E extends Enum<E>> void visitEnum(String descriptor, String value,
|
||||
Consumer<E> consumer) {
|
||||
|
||||
public <E extends Enum<E>> void visitEnum(String descriptor, String value, Consumer<E> consumer) {
|
||||
String className = Type.getType(descriptor).getClassName();
|
||||
Class<E> type = (Class<E>) ClassUtils.resolveClassName(className, this.classLoader);
|
||||
E enumValue = Enum.valueOf(type, value);
|
||||
if (enumValue != null) {
|
||||
consumer.accept(enumValue);
|
||||
}
|
||||
consumer.accept(Enum.valueOf(type, value));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Annotation> AnnotationVisitor visitAnnotation(String descriptor,
|
||||
Consumer<MergedAnnotation<T>> consumer) {
|
||||
@Nullable
|
||||
private <T extends Annotation> AnnotationVisitor visitAnnotation(
|
||||
String descriptor, Consumer<MergedAnnotation<T>> consumer) {
|
||||
|
||||
String className = Type.getType(descriptor).getClassName();
|
||||
if (AnnotationFilter.PLAIN.matches(className)) {
|
||||
return null;
|
||||
}
|
||||
Class<T> type = (Class<T>) ClassUtils.resolveClassName(className,
|
||||
this.classLoader);
|
||||
return new MergedAnnotationReadingVisitor<>(this.classLoader, this.source, type,
|
||||
consumer);
|
||||
Class<T> type = (Class<T>) ClassUtils.resolveClassName(className, this.classLoader);
|
||||
return new MergedAnnotationReadingVisitor<>(this.classLoader, this.source, type, consumer);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
static <A extends Annotation> AnnotationVisitor get(@Nullable ClassLoader classLoader,
|
||||
@Nullable Supplier<Object> sourceSupplier, String descriptor, boolean visible,
|
||||
Consumer<MergedAnnotation<A>> consumer) {
|
||||
|
||||
if (!visible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String typeName = Type.getType(descriptor).getClassName();
|
||||
if (AnnotationFilter.PLAIN.matches(typeName)) {
|
||||
return null;
|
||||
}
|
||||
Object source = sourceSupplier != null ? sourceSupplier.get() : null;
|
||||
|
||||
Object source = (sourceSupplier != null ? sourceSupplier.get() : null);
|
||||
try {
|
||||
Class<A> annotationType = (Class<A>) ClassUtils.forName(typeName,
|
||||
classLoader);
|
||||
return new MergedAnnotationReadingVisitor<>(classLoader, source,
|
||||
annotationType, consumer);
|
||||
Class<A> annotationType = (Class<A>) ClassUtils.forName(typeName, classLoader);
|
||||
return new MergedAnnotationReadingVisitor<>(classLoader, source, annotationType, consumer);
|
||||
}
|
||||
catch (ClassNotFoundException | LinkageError ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link AnnotationVisitor} to deal with array attributes.
|
||||
*/
|
||||
@@ -170,21 +168,19 @@ class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVis
|
||||
|
||||
@Override
|
||||
public void visitEnum(String name, String descriptor, String value) {
|
||||
MergedAnnotationReadingVisitor.this.visitEnum(descriptor, value,
|
||||
enumValue -> this.elements.add(enumValue));
|
||||
MergedAnnotationReadingVisitor.this.visitEnum(descriptor, value, this.elements::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationVisitor visitAnnotation(String name, String descriptor) {
|
||||
return MergedAnnotationReadingVisitor.this.visitAnnotation(descriptor,
|
||||
annotation -> this.elements.add(annotation));
|
||||
return MergedAnnotationReadingVisitor.this.visitAnnotation(descriptor, this.elements::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
Class<?> componentType = getComponentType();
|
||||
Object[] array = (Object[]) Array.newInstance(componentType,
|
||||
this.elements.size());
|
||||
Object[] array = (Object[]) Array.newInstance(componentType, this.elements.size());
|
||||
this.consumer.accept(this.elements.toArray(array));
|
||||
}
|
||||
|
||||
@@ -193,12 +189,11 @@ class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVis
|
||||
return Object.class;
|
||||
}
|
||||
Object firstElement = this.elements.get(0);
|
||||
if(firstElement instanceof Enum) {
|
||||
if (firstElement instanceof Enum) {
|
||||
return ((Enum<?>) firstElement).getDeclaringClass();
|
||||
}
|
||||
return firstElement.getClass();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
|
||||
if (!visible) {
|
||||
return null;
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link AnnotationMetadata} created from a
|
||||
* {@link SimpleAnnotationMetadataReadingVistor}.
|
||||
* {@link SimpleAnnotationMetadataReadingVisitor}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 5.2
|
||||
@@ -39,8 +39,10 @@ final class SimpleAnnotationMetadata implements AnnotationMetadata {
|
||||
|
||||
private final int access;
|
||||
|
||||
@Nullable
|
||||
private final String enclosingClassName;
|
||||
|
||||
@Nullable
|
||||
private final String superClassName;
|
||||
|
||||
private final boolean independentInnerClass;
|
||||
@@ -53,12 +55,14 @@ final class SimpleAnnotationMetadata implements AnnotationMetadata {
|
||||
|
||||
private final MergedAnnotations annotations;
|
||||
|
||||
@Nullable
|
||||
private Set<String> annotationTypes;
|
||||
|
||||
SimpleAnnotationMetadata(String className, int access, String enclosingClassName,
|
||||
String superClassName, boolean independentInnerClass, String[] interfaceNames,
|
||||
String[] memberClassNames, MethodMetadata[] annotatedMethods,
|
||||
MergedAnnotations annotations) {
|
||||
|
||||
SimpleAnnotationMetadata(String className, int access, @Nullable String enclosingClassName,
|
||||
@Nullable String superClassName, boolean independentInnerClass, String[] interfaceNames,
|
||||
String[] memberClassNames, MethodMetadata[] annotatedMethods, MergedAnnotations annotations) {
|
||||
|
||||
this.className = className;
|
||||
this.access = access;
|
||||
this.enclosingClassName = enclosingClassName;
|
||||
@@ -97,7 +101,7 @@ final class SimpleAnnotationMetadata implements AnnotationMetadata {
|
||||
|
||||
@Override
|
||||
public boolean isIndependent() {
|
||||
return this.enclosingClassName == null || this.independentInnerClass;
|
||||
return (this.enclosingClassName == null || this.independentInnerClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -39,7 +40,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Phillip Webb
|
||||
* @since 5.2
|
||||
*/
|
||||
class SimpleAnnotationMetadataReadingVistor extends ClassVisitor {
|
||||
final class SimpleAnnotationMetadataReadingVisitor extends ClassVisitor {
|
||||
|
||||
@Nullable
|
||||
private final ClassLoader classLoader;
|
||||
@@ -48,10 +49,12 @@ class SimpleAnnotationMetadataReadingVistor extends ClassVisitor {
|
||||
|
||||
private int access;
|
||||
|
||||
@Nullable
|
||||
private String superClassName;
|
||||
|
||||
private String[] interfaceNames;
|
||||
private String[] interfaceNames = new String[0];
|
||||
|
||||
@Nullable
|
||||
private String enclosingClassName;
|
||||
|
||||
private boolean independentInnerClass;
|
||||
@@ -62,18 +65,23 @@ class SimpleAnnotationMetadataReadingVistor extends ClassVisitor {
|
||||
|
||||
private List<SimpleMethodMetadata> annotatedMethods = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
private SimpleAnnotationMetadata metadata;
|
||||
|
||||
@Nullable
|
||||
private Source source;
|
||||
|
||||
SimpleAnnotationMetadataReadingVistor(@Nullable ClassLoader classLoader) {
|
||||
|
||||
SimpleAnnotationMetadataReadingVisitor(@Nullable ClassLoader classLoader) {
|
||||
super(SpringAsmInfo.ASM_VERSION);
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature,
|
||||
@Nullable String supername, String[] interfaces) {
|
||||
|
||||
this.className = toClassName(name);
|
||||
this.access = access;
|
||||
if (supername != null && !isInterface(access)) {
|
||||
@@ -107,21 +115,24 @@ class SimpleAnnotationMetadataReadingVistor extends ClassVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||
return MergedAnnotationReadingVisitor.get(this.classLoader, this::getSource,
|
||||
descriptor, visible, this.annotations::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||
String signature, String[] exceptions) {
|
||||
@Nullable
|
||||
public MethodVisitor visitMethod(
|
||||
int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
|
||||
// Skip bridge methods - we're only interested in original
|
||||
// annotation-defining user methods. On JDK 8, we'd otherwise run into
|
||||
// double detection of the same annotated method...
|
||||
if (isBridge(access)) {
|
||||
return null;
|
||||
}
|
||||
return new SimpleMethodMetadataReadingVistor(this.classLoader, this.className,
|
||||
return new SimpleMethodMetadataReadingVisitor(this.classLoader, this.className,
|
||||
access, name, descriptor, this.annotatedMethods::add);
|
||||
}
|
||||
|
||||
@@ -136,6 +147,7 @@ class SimpleAnnotationMetadataReadingVistor extends ClassVisitor {
|
||||
}
|
||||
|
||||
public SimpleAnnotationMetadata getMetadata() {
|
||||
Assert.state(this.metadata != null, "AnnotationMetadata not initialized");
|
||||
return this.metadata;
|
||||
}
|
||||
|
||||
@@ -46,14 +46,13 @@ final class SimpleMetadataReader implements MetadataReader {
|
||||
|
||||
|
||||
SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
|
||||
SimpleAnnotationMetadataReadingVistor visitor = new SimpleAnnotationMetadataReadingVistor(classLoader);
|
||||
SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader);
|
||||
getClassReader(resource).accept(visitor, PARSING_OPTIONS);
|
||||
this.resource = resource;
|
||||
this.annotationMetadata = visitor.getMetadata();
|
||||
}
|
||||
|
||||
private ClassReader getClassReader(Resource resource)
|
||||
throws IOException, NestedIOException {
|
||||
private static ClassReader getClassReader(Resource resource) throws IOException {
|
||||
try (InputStream is = new BufferedInputStream(resource.getInputStream())) {
|
||||
try {
|
||||
return new ClassReader(is);
|
||||
@@ -65,6 +64,7 @@ final class SimpleMetadataReader implements MetadataReader {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Resource getResource() {
|
||||
return this.resource;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.springframework.core.type.MethodMetadata;
|
||||
|
||||
/**
|
||||
* {@link MethodMetadata} created from a
|
||||
* {@link SimpleMethodMetadataReadingVistor}.
|
||||
* {@link SimpleMethodMetadataReadingVisitor}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 5.2
|
||||
@@ -39,8 +39,10 @@ final class SimpleMethodMetadata implements MethodMetadata {
|
||||
|
||||
private final MergedAnnotations annotations;
|
||||
|
||||
|
||||
public SimpleMethodMetadata(String methodName, int access, String declaringClassName,
|
||||
String returnTypeName, MergedAnnotations annotations) {
|
||||
|
||||
this.methodName = methodName;
|
||||
this.access = access;
|
||||
this.declaringClassName = declaringClassName;
|
||||
@@ -48,6 +50,7 @@ final class SimpleMethodMetadata implements MethodMetadata {
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getMethodName() {
|
||||
return this.methodName;
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Phillip Webb
|
||||
* @since 5.2
|
||||
*/
|
||||
class SimpleMethodMetadataReadingVistor extends MethodVisitor {
|
||||
final class SimpleMethodMetadataReadingVisitor extends MethodVisitor {
|
||||
|
||||
@Nullable
|
||||
private final ClassLoader classLoader;
|
||||
@@ -48,16 +48,17 @@ class SimpleMethodMetadataReadingVistor extends MethodVisitor {
|
||||
|
||||
private final String descriptor;
|
||||
|
||||
private final List<MergedAnnotation<?>> annotations = new ArrayList<MergedAnnotation<?>>(
|
||||
4);
|
||||
private final List<MergedAnnotation<?>> annotations = new ArrayList<>(4);
|
||||
|
||||
private final Consumer<SimpleMethodMetadata> consumer;
|
||||
|
||||
@Nullable
|
||||
private Source source;
|
||||
|
||||
SimpleMethodMetadataReadingVistor(@Nullable ClassLoader classLoader,
|
||||
String declaringClassName, int access, String name, String descriptor,
|
||||
Consumer<SimpleMethodMetadata> consumer) {
|
||||
|
||||
SimpleMethodMetadataReadingVisitor(@Nullable ClassLoader classLoader, String declaringClassName,
|
||||
int access, String name, String descriptor, Consumer<SimpleMethodMetadata> consumer) {
|
||||
|
||||
super(SpringAsmInfo.ASM_VERSION);
|
||||
this.classLoader = classLoader;
|
||||
this.declaringClassName = declaringClassName;
|
||||
@@ -67,7 +68,9 @@ class SimpleMethodMetadataReadingVistor extends MethodVisitor {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||
return MergedAnnotationReadingVisitor.get(this.classLoader, this::getSource,
|
||||
descriptor, visible, this.annotations::add);
|
||||
@@ -93,6 +96,7 @@ class SimpleMethodMetadataReadingVistor extends MethodVisitor {
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@link MergedAnnotation} source.
|
||||
*/
|
||||
@@ -104,7 +108,8 @@ class SimpleMethodMetadataReadingVistor extends MethodVisitor {
|
||||
|
||||
private final String descriptor;
|
||||
|
||||
private String string;
|
||||
@Nullable
|
||||
private String toStringValue;
|
||||
|
||||
Source(String declaringClassName, String name, String descriptor) {
|
||||
this.declaringClassName = declaringClassName;
|
||||
@@ -122,25 +127,22 @@ class SimpleMethodMetadataReadingVistor extends MethodVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
if (other == null || getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Source other = (Source) obj;
|
||||
boolean result = true;
|
||||
result = result &= this.declaringClassName.equals(other.declaringClassName);
|
||||
result = result &= this.name.equals(other.name);
|
||||
result = result &= this.descriptor.equals(other.descriptor);
|
||||
return result;
|
||||
Source otherSource = (Source) other;
|
||||
return (this.declaringClassName.equals(otherSource.declaringClassName) &&
|
||||
this.name.equals(otherSource.name) && this.descriptor.equals(otherSource.descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String string = this.string;
|
||||
if (string == null) {
|
||||
String value = this.toStringValue;
|
||||
if (value == null) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(this.declaringClassName);
|
||||
builder.append(".");
|
||||
@@ -151,12 +153,11 @@ class SimpleMethodMetadataReadingVistor extends MethodVisitor {
|
||||
builder.append(type.getClassName());
|
||||
}
|
||||
builder.append(")");
|
||||
string = builder.toString();
|
||||
this.string = string;
|
||||
value = builder.toString();
|
||||
this.toStringValue = value;
|
||||
}
|
||||
return string;
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,11 +18,10 @@ package org.springframework.core.type.classreading;
|
||||
|
||||
import org.springframework.core.type.AbstractAnnotationMetadataTests;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
||||
|
||||
/**
|
||||
* Tests for {@link SimpleAnnotationMetadata} and
|
||||
* {@link SimpleAnnotationMetadataReadingVistor}.
|
||||
* {@link SimpleAnnotationMetadataReadingVisitor}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
|
||||
@@ -18,11 +18,10 @@ package org.springframework.core.type.classreading;
|
||||
|
||||
import org.springframework.core.type.AbstractMethodMetadataTests;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
|
||||
|
||||
/**
|
||||
* Tests for {@link SimpleMethodMetadata} and
|
||||
* {@link SimpleMethodMetadataReadingVistor}.
|
||||
* {@link SimpleMethodMetadataReadingVisitor}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user