Add MergedAnnotations support to meta-data classes
Add `AnnotatedTypeMetaData.getAnnotations()` that can be used to access annotation details using the `MergedAnnotations` interface. Where possible, the existing annotation methods have been migrated to call `getAnnotation()`, rather than needing their own implementation. The existing ASM based meta-data implementations have not been updated since they will be deprecated and replaced in a subsequent commit. See gh-22884
This commit is contained in:
parent
30ba80a3c3
commit
8c2ccfe6a3
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
@ -16,8 +16,15 @@
|
|||
|
||||
package org.springframework.core.type;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotation.Adapt;
|
||||
import org.springframework.core.annotation.MergedAnnotationCollectors;
|
||||
import org.springframework.core.annotation.MergedAnnotationPredicates;
|
||||
import org.springframework.core.annotation.MergedAnnotationSelectors;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
|
@ -38,6 +45,13 @@ import org.springframework.util.MultiValueMap;
|
|||
*/
|
||||
public interface AnnotatedTypeMetadata {
|
||||
|
||||
/**
|
||||
* Return annotation details based on the direct annotations of the
|
||||
* underlying element.
|
||||
* @return merged annotations based on the direct annotations
|
||||
*/
|
||||
MergedAnnotations getAnnotations();
|
||||
|
||||
/**
|
||||
* Determine whether the underlying element has an annotation or meta-annotation
|
||||
* of the given type defined.
|
||||
|
@ -47,7 +61,9 @@ public interface AnnotatedTypeMetadata {
|
|||
* type to look for
|
||||
* @return whether a matching annotation is defined
|
||||
*/
|
||||
boolean isAnnotated(String annotationName);
|
||||
default boolean isAnnotated(String annotationName) {
|
||||
return getAnnotations().isPresent(annotationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the attributes of the annotation of the given type, if any (i.e. if
|
||||
|
@ -78,7 +94,16 @@ public interface AnnotatedTypeMetadata {
|
|||
* {@code null} if no matching annotation is defined.
|
||||
*/
|
||||
@Nullable
|
||||
Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);
|
||||
default Map<String, Object> getAnnotationAttributes(String annotationName,
|
||||
boolean classValuesAsString) {
|
||||
|
||||
MergedAnnotation<Annotation> annotation = getAnnotations().get(annotationName,
|
||||
null, MergedAnnotationSelectors.firstDirectlyDeclared());
|
||||
if (!annotation.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
return annotation.asAnnotationAttributes(Adapt.values(classValuesAsString, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all attributes of all annotations of the given type, if any (i.e. if
|
||||
|
@ -109,6 +134,15 @@ public interface AnnotatedTypeMetadata {
|
|||
* @see #getAllAnnotationAttributes(String)
|
||||
*/
|
||||
@Nullable
|
||||
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
|
||||
default MultiValueMap<String, Object> getAllAnnotationAttributes(
|
||||
String annotationName, boolean classValuesAsString) {
|
||||
|
||||
Adapt[] adaptations = Adapt.values(classValuesAsString, true);
|
||||
return getAnnotations().stream(annotationName)
|
||||
.filter(MergedAnnotationPredicates.unique(MergedAnnotation::getTypeHierarchy))
|
||||
.map(MergedAnnotation::withNonMergedAttributes)
|
||||
.collect(MergedAnnotationCollectors.toMultiValueMap(map ->
|
||||
map.isEmpty() ? null : map, adaptations));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
@ -16,7 +16,14 @@
|
|||
|
||||
package org.springframework.core.type;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
|
||||
|
||||
/**
|
||||
* Interface that defines abstract access to the annotations of a specific
|
||||
|
@ -38,7 +45,12 @@ public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata
|
|||
* are <em>present</em> on the underlying class.
|
||||
* @return the annotation type names
|
||||
*/
|
||||
Set<String> getAnnotationTypes();
|
||||
default Set<String> getAnnotationTypes() {
|
||||
return getAnnotations().stream()
|
||||
.filter(MergedAnnotation::isDirectlyPresent)
|
||||
.map(annotation -> annotation.getType().getName())
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified class names of all meta-annotation types that
|
||||
|
@ -47,7 +59,15 @@ public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata
|
|||
* type to look for
|
||||
* @return the meta-annotation type names, or an empty set if none found
|
||||
*/
|
||||
Set<String> getMetaAnnotationTypes(String annotationName);
|
||||
default Set<String> getMetaAnnotationTypes(String annotationName) {
|
||||
MergedAnnotation<?> annotation = getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent);
|
||||
if (!annotation.isPresent()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream()
|
||||
.map(mergedAnnotation -> mergedAnnotation.getType().getName())
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an annotation of the given type is <em>present</em> on
|
||||
|
@ -57,7 +77,7 @@ public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata
|
|||
* @return {@code true} if a matching annotation is present
|
||||
*/
|
||||
default boolean hasAnnotation(String annotationName) {
|
||||
return getAnnotationTypes().contains(annotationName);
|
||||
return getAnnotations().isDirectlyPresent(annotationName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,7 +87,10 @@ public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata
|
|||
* meta-annotation type to look for
|
||||
* @return {@code true} if a matching meta-annotation is present
|
||||
*/
|
||||
boolean hasMetaAnnotation(String metaAnnotationName);
|
||||
default boolean hasMetaAnnotation(String metaAnnotationName) {
|
||||
return getAnnotations().get(metaAnnotationName,
|
||||
MergedAnnotation::isMetaPresent).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the underlying class has any methods that are
|
||||
|
@ -75,7 +98,9 @@ public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata
|
|||
* @param annotationName the fully qualified class name of the annotation
|
||||
* type to look for
|
||||
*/
|
||||
boolean hasAnnotatedMethods(String annotationName);
|
||||
default boolean hasAnnotatedMethods(String annotationName) {
|
||||
return !getAnnotatedMethods(annotationName).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the method metadata for all methods that are annotated
|
||||
|
|
|
@ -24,7 +24,11 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationFilter;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
|
||||
import org.springframework.core.annotation.RepeatableContainers;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
@ -42,10 +46,11 @@ import org.springframework.util.ReflectionUtils;
|
|||
*/
|
||||
public class StandardAnnotationMetadata extends StandardClassMetadata implements AnnotationMetadata {
|
||||
|
||||
private final Annotation[] annotations;
|
||||
private final MergedAnnotations mergedAnnotations;
|
||||
|
||||
private final boolean nestedAnnotationsAsMap;
|
||||
|
||||
private Set<String> annotationTypes;
|
||||
|
||||
/**
|
||||
* Create a new {@code StandardAnnotationMetadata} wrapper for the given Class.
|
||||
|
@ -69,72 +74,49 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
|||
*/
|
||||
public StandardAnnotationMetadata(Class<?> introspectedClass, boolean nestedAnnotationsAsMap) {
|
||||
super(introspectedClass);
|
||||
this.annotations = introspectedClass.getDeclaredAnnotations();
|
||||
this.mergedAnnotations = MergedAnnotations.from(introspectedClass,
|
||||
SearchStrategy.DIRECT, RepeatableContainers.none(),
|
||||
AnnotationFilter.NONE);
|
||||
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MergedAnnotations getAnnotations() {
|
||||
return this.mergedAnnotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAnnotationTypes() {
|
||||
Set<String> types = new LinkedHashSet<>();
|
||||
for (Annotation ann : this.annotations) {
|
||||
if (!AnnotationUtils.isInJavaLangAnnotationPackage(ann.annotationType().getName())) {
|
||||
types.add(ann.annotationType().getName());
|
||||
}
|
||||
Set<String> annotationTypes = this.annotationTypes;
|
||||
if (annotationTypes == null) {
|
||||
annotationTypes = Collections.unmodifiableSet(
|
||||
AnnotationMetadata.super.getAnnotationTypes());
|
||||
this.annotationTypes = annotationTypes;
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getMetaAnnotationTypes(String annotationName) {
|
||||
if (AnnotationUtils.isInJavaLangAnnotationPackage(annotationName)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return (this.annotations.length > 0 ?
|
||||
AnnotatedElementUtils.getMetaAnnotationTypes(getIntrospectedClass(), annotationName) :
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnnotation(String annotationName) {
|
||||
if (AnnotationUtils.isInJavaLangAnnotationPackage(annotationName)) {
|
||||
return false;
|
||||
}
|
||||
for (Annotation ann : this.annotations) {
|
||||
if (ann.annotationType().getName().equals(annotationName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMetaAnnotation(String annotationName) {
|
||||
if (AnnotationUtils.isInJavaLangAnnotationPackage(annotationName)) {
|
||||
return false;
|
||||
}
|
||||
return (this.annotations.length > 0 &&
|
||||
AnnotatedElementUtils.hasMetaAnnotationTypes(getIntrospectedClass(), annotationName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnnotated(String annotationName) {
|
||||
return (this.annotations.length > 0 &&
|
||||
AnnotatedElementUtils.isAnnotated(getIntrospectedClass(), annotationName));
|
||||
return annotationTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
return (this.annotations.length > 0 ? AnnotatedElementUtils.getMergedAnnotationAttributes(
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap) : null);
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return AnnotationMetadata.super.getAnnotationAttributes(annotationName,
|
||||
classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getMergedAnnotationAttributes(
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
return (this.annotations.length > 0 ? AnnotatedElementUtils.getAllAnnotationAttributes(
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap) : null);
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return AnnotationMetadata.super.getAllAnnotationAttributes(annotationName,
|
||||
classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getAllAnnotationAttributes(
|
||||
getIntrospectedClass(), annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -143,8 +125,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
|||
try {
|
||||
Method[] methods = ReflectionUtils.getDeclaredMethods(getIntrospectedClass());
|
||||
for (Method method : methods) {
|
||||
if (!method.isBridge() && method.getAnnotations().length > 0 &&
|
||||
AnnotatedElementUtils.isAnnotated(method, annotationName)) {
|
||||
if (isAnnotatedMethod(method, annotationName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -158,13 +139,15 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
|||
|
||||
@Override
|
||||
public Set<MethodMetadata> getAnnotatedMethods(String annotationName) {
|
||||
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<>(4);
|
||||
Set<MethodMetadata> annotatedMethods = null;
|
||||
if (AnnotationUtils.isCandidateClass(getIntrospectedClass(), annotationName)) {
|
||||
try {
|
||||
Method[] methods = getIntrospectedClass().getDeclaredMethods();
|
||||
Method[] methods = ReflectionUtils.getDeclaredMethods(getIntrospectedClass());
|
||||
for (Method method : methods) {
|
||||
if (!method.isBridge() && method.getAnnotations().length > 0 &&
|
||||
AnnotatedElementUtils.isAnnotated(method, annotationName)) {
|
||||
if (isAnnotatedMethod(method, annotationName)) {
|
||||
if (annotatedMethods == null) {
|
||||
annotatedMethods = new LinkedHashSet<>(4);
|
||||
}
|
||||
annotatedMethods.add(new StandardMethodMetadata(method, this.nestedAnnotationsAsMap));
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +156,12 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
|||
throw new IllegalStateException("Failed to introspect annotated methods on " + getIntrospectedClass(), ex);
|
||||
}
|
||||
}
|
||||
return annotatedMethods;
|
||||
return annotatedMethods != null ? annotatedMethods : Collections.emptySet();
|
||||
}
|
||||
|
||||
private boolean isAnnotatedMethod(Method method, String annotationName) {
|
||||
return !method.isBridge() && method.getAnnotations().length > 0 &&
|
||||
AnnotatedElementUtils.isAnnotated(method, annotationName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
|
@ -21,6 +21,10 @@ import java.lang.reflect.Modifier;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationFilter;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
|
||||
import org.springframework.core.annotation.RepeatableContainers;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
@ -41,6 +45,8 @@ public class StandardMethodMetadata implements MethodMetadata {
|
|||
|
||||
private final boolean nestedAnnotationsAsMap;
|
||||
|
||||
private final MergedAnnotations mergedAnnotations;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new StandardMethodMetadata wrapper for the given Method.
|
||||
|
@ -65,8 +71,15 @@ public class StandardMethodMetadata implements MethodMetadata {
|
|||
Assert.notNull(introspectedMethod, "Method must not be null");
|
||||
this.introspectedMethod = introspectedMethod;
|
||||
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
|
||||
this.mergedAnnotations = MergedAnnotations.from(introspectedMethod,
|
||||
SearchStrategy.DIRECT, RepeatableContainers.none(),
|
||||
AnnotationFilter.PLAIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergedAnnotations getAnnotations() {
|
||||
return this.mergedAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying Method.
|
||||
|
@ -107,17 +120,19 @@ public class StandardMethodMetadata implements MethodMetadata {
|
|||
|
||||
@Override
|
||||
public boolean isOverridable() {
|
||||
return (!isStatic() && !isFinal() && !Modifier.isPrivate(this.introspectedMethod.getModifiers()));
|
||||
return !isStatic() && !isFinal() && !isPrivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnnotated(String annotationName) {
|
||||
return AnnotatedElementUtils.isAnnotated(this.introspectedMethod, annotationName);
|
||||
private boolean isPrivate() {
|
||||
return Modifier.isPrivate(this.introspectedMethod.getModifiers());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return MethodMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod,
|
||||
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
}
|
||||
|
@ -125,6 +140,9 @@ public class StandardMethodMetadata implements MethodMetadata {
|
|||
@Override
|
||||
@Nullable
|
||||
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return MethodMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod,
|
||||
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.springframework.asm.Opcodes;
|
|||
import org.springframework.asm.Type;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
@ -72,6 +73,11 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MergedAnnotations getAnnotations() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
// Skip bridge methods - we're only interested in original annotation-defining user methods.
|
||||
|
@ -129,6 +135,11 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
|
|||
this.attributesMap.containsKey(annotationName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnnotation(String annotationName) {
|
||||
return getAnnotationTypes().contains(annotationName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.springframework.asm.Opcodes;
|
|||
import org.springframework.asm.SpringAsmInfo;
|
||||
import org.springframework.asm.Type;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.type.MethodMetadata;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
@ -77,6 +78,11 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MergedAnnotations getAnnotations() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
|
||||
if (!visible) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.type.AbstractAnnotationMetadataTests.TestMemberClass.TestMemberClassInnerClass;
|
||||
import org.springframework.core.type.AbstractAnnotationMetadataTests.TestMemberClass.TestMemberClassInnerInterface;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
@ -137,6 +138,16 @@ public abstract class AbstractAnnotationMetadataTests {
|
|||
assertThat(get(TestClass.class).getMemberClassNames()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotationsReturnsDirectAnnotations() {
|
||||
AnnotationMetadata metadata = get(WithDirectAnnotations.class);
|
||||
assertThat(metadata.getAnnotations().stream().filter(
|
||||
MergedAnnotation::isDirectlyPresent).map(
|
||||
a -> a.getType().getName())).containsExactlyInAnyOrder(
|
||||
DirectAnnotation1.class.getName(),
|
||||
DirectAnnotation2.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAnnotatedWhenMatchesDirectAnnotationReturnsTrue() {
|
||||
assertThat(get(WithDirectAnnotations.class).isAnnotated(
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
@ -91,6 +92,16 @@ public abstract class AbstractMethodMetadataTests {
|
|||
assertThat(getTagged(WithPrivateMethod.class).isOverridable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotationsReturnsDirectAnnotations() {
|
||||
MethodMetadata metadata = getTagged(WithDirectAnnotation.class);
|
||||
assertThat(metadata.getAnnotations().stream().filter(
|
||||
MergedAnnotation::isDirectlyPresent).map(
|
||||
a -> a.getType().getName())).containsExactlyInAnyOrder(
|
||||
Tag.class.getName(),
|
||||
DirectAnnotation.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAnnotatedWhenMatchesDirectAnnotationReturnsTrue() {
|
||||
assertThat(getTagged(WithDirectAnnotation.class).isAnnotated(
|
||||
|
|
|
@ -25,8 +25,11 @@ import org.springframework.core.io.Resource;
|
|||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.type.AbstractAnnotationMetadataTests;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link AnnotationMetadataReadingVisitor}.
|
||||
*
|
||||
|
@ -58,4 +61,10 @@ public class AnnotationMetadataReadingVisitorTests
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAnnotationsReturnsDirectAnnotations() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
|
||||
super::getAnnotationsReturnsDirectAnnotations);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,13 +25,18 @@ import org.springframework.core.io.Resource;
|
|||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.type.AbstractMethodMetadataTests;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor;
|
||||
import org.springframework.core.type.classreading.MethodMetadataReadingVisitor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link MethodMetadataReadingVisitor}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MethodMetadataReadingVisitorTests extends AbstractMethodMetadataTests {
|
||||
|
||||
@Override
|
||||
|
@ -57,4 +62,10 @@ public class MethodMetadataReadingVisitorTests extends AbstractMethodMetadataTes
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAnnotationsReturnsDirectAnnotations() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(
|
||||
super::getAnnotationsReturnsDirectAnnotations);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue