Refined retrieval of plain annotations through direct presence checks
Shortcut checks apply for hasPlainJavaAnnotationsOnly types as well now. Closes gh-22685
This commit is contained in:
parent
cb84c56f19
commit
c9857702e4
|
@ -85,6 +85,7 @@ dependencies {
|
||||||
optional("io.netty:netty-buffer")
|
optional("io.netty:netty-buffer")
|
||||||
testCompile("io.projectreactor:reactor-test")
|
testCompile("io.projectreactor:reactor-test")
|
||||||
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
testCompile("org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}")
|
||||||
|
testCompile("com.google.code.findbugs:jsr305:3.0.2")
|
||||||
testCompile("org.xmlunit:xmlunit-matchers:2.6.2")
|
testCompile("org.xmlunit:xmlunit-matchers:2.6.2")
|
||||||
testCompile("javax.xml.bind:jaxb-api:2.3.1")
|
testCompile("javax.xml.bind:jaxb-api:2.3.1")
|
||||||
testCompile("com.fasterxml.woodstox:woodstox-core:5.2.0") {
|
testCompile("com.fasterxml.woodstox:woodstox-core:5.2.0") {
|
||||||
|
|
|
@ -200,15 +200,12 @@ public abstract class AnnotatedElementUtils {
|
||||||
* @since 4.2.3
|
* @since 4.2.3
|
||||||
* @see #hasAnnotation(AnnotatedElement, Class)
|
* @see #hasAnnotation(AnnotatedElement, Class)
|
||||||
*/
|
*/
|
||||||
public static boolean isAnnotated(AnnotatedElement element,Class<? extends Annotation> annotationType) {
|
public static boolean isAnnotated(AnnotatedElement element, Class<? extends Annotation> annotationType) {
|
||||||
// Shortcut: directly present on the element, with no processing needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
||||||
return element.isAnnotationPresent(annotationType);
|
return element.isAnnotationPresent(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return getAnnotations(element).isPresent(annotationType);
|
return getAnnotations(element).isPresent(annotationType);
|
||||||
}
|
}
|
||||||
|
@ -332,13 +329,10 @@ public abstract class AnnotatedElementUtils {
|
||||||
@Nullable
|
@Nullable
|
||||||
public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
|
public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
|
||||||
// Shortcut: directly present on the element, with no merging needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
||||||
return element.getDeclaredAnnotation(annotationType);
|
return element.getDeclaredAnnotation(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return getAnnotations(element)
|
return getAnnotations(element)
|
||||||
.get(annotationType, null, MergedAnnotationSelectors.firstDirectlyDeclared())
|
.get(annotationType, null, MergedAnnotationSelectors.firstDirectlyDeclared())
|
||||||
|
@ -528,14 +522,11 @@ public abstract class AnnotatedElementUtils {
|
||||||
* @see #isAnnotated(AnnotatedElement, Class)
|
* @see #isAnnotated(AnnotatedElement, Class)
|
||||||
*/
|
*/
|
||||||
public static boolean hasAnnotation(AnnotatedElement element, Class<? extends Annotation> annotationType) {
|
public static boolean hasAnnotation(AnnotatedElement element, Class<? extends Annotation> annotationType) {
|
||||||
// Shortcut: directly present on the element, with no processing needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
||||||
return element.isAnnotationPresent(annotationType);
|
return element.isAnnotationPresent(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return findAnnotations(element).isPresent(annotationType);
|
return findAnnotations(element).isPresent(annotationType);
|
||||||
}
|
}
|
||||||
|
@ -633,13 +624,10 @@ public abstract class AnnotatedElementUtils {
|
||||||
@Nullable
|
@Nullable
|
||||||
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
|
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
|
||||||
// Shortcut: directly present on the element, with no merging needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
||||||
return element.getDeclaredAnnotation(annotationType);
|
return element.getDeclaredAnnotation(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return findAnnotations(element)
|
return findAnnotations(element)
|
||||||
.get(annotationType, null, MergedAnnotationSelectors.firstDirectlyDeclared())
|
.get(annotationType, null, MergedAnnotationSelectors.firstDirectlyDeclared())
|
||||||
|
|
|
@ -28,17 +28,16 @@ import java.lang.annotation.Annotation;
|
||||||
public interface AnnotationFilter {
|
public interface AnnotationFilter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AnnotationFilter} that matches annotations is in the
|
* {@link AnnotationFilter} that matches annotations in the
|
||||||
* {@code java.lang.*} or in the
|
* {@code java.lang.*} and {@code org.springframework.lang.*} packages.
|
||||||
* {@code org.springframework.lang.*} package.
|
|
||||||
*/
|
*/
|
||||||
AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang");
|
AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AnnotationFilter} that matches annotations in the
|
* {@link AnnotationFilter} that matches annotations in the
|
||||||
* {@code java.lang.*} package.
|
* {@code java.*}/{@code javax.*} namespaces.
|
||||||
*/
|
*/
|
||||||
AnnotationFilter JAVA = packages("java.lang");
|
AnnotationFilter JAVA = packages("java", "javax");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AnnotationFilter} that never matches and can be used when no
|
* {@link AnnotationFilter} that never matches and can be used when no
|
||||||
|
|
|
@ -210,13 +210,10 @@ public abstract class AnnotationUtils {
|
||||||
@Nullable
|
@Nullable
|
||||||
public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
|
public static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
|
||||||
// Shortcut: directly present on the element, with no merging needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotatedElement)) {
|
||||||
return annotatedElement.getAnnotation(annotationType);
|
return annotatedElement.getAnnotation(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotatedElement)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return MergedAnnotations.from(annotatedElement, SearchStrategy.INHERITED_ANNOTATIONS,
|
return MergedAnnotations.from(annotatedElement, SearchStrategy.INHERITED_ANNOTATIONS,
|
||||||
RepeatableContainers.none(), AnnotationFilter.PLAIN)
|
RepeatableContainers.none(), AnnotationFilter.PLAIN)
|
||||||
|
@ -483,13 +480,10 @@ public abstract class AnnotationUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Shortcut: directly present on the element, with no merging needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotatedElement)) {
|
||||||
return annotatedElement.getDeclaredAnnotation(annotationType);
|
return annotatedElement.getDeclaredAnnotation(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotatedElement)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return MergedAnnotations.from(annotatedElement, SearchStrategy.INHERITED_ANNOTATIONS)
|
return MergedAnnotations.from(annotatedElement, SearchStrategy.INHERITED_ANNOTATIONS)
|
||||||
.get(annotationType).withNonMergedAttributes()
|
.get(annotationType).withNonMergedAttributes()
|
||||||
|
@ -517,13 +511,10 @@ public abstract class AnnotationUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Shortcut: directly present on the element, with no merging needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(method)) {
|
||||||
return method.getDeclaredAnnotation(annotationType);
|
return method.getDeclaredAnnotation(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(method)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return MergedAnnotations.from(method, SearchStrategy.EXHAUSTIVE)
|
return MergedAnnotations.from(method, SearchStrategy.EXHAUSTIVE)
|
||||||
.get(annotationType).withNonMergedAttributes()
|
.get(annotationType).withNonMergedAttributes()
|
||||||
|
@ -558,13 +549,10 @@ public abstract class AnnotationUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Shortcut: directly present on the element, with no merging needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType)) {
|
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
||||||
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
|
||||||
return clazz.getDeclaredAnnotation(annotationType);
|
return clazz.getDeclaredAnnotation(annotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return MergedAnnotations.from(clazz, SearchStrategy.EXHAUSTIVE)
|
return MergedAnnotations.from(clazz, SearchStrategy.EXHAUSTIVE)
|
||||||
.get(annotationType).withNonMergedAttributes()
|
.get(annotationType).withNonMergedAttributes()
|
||||||
|
@ -710,17 +698,13 @@ public abstract class AnnotationUtils {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Shortcut: directly present on the element, with no merging needed?
|
// Shortcut: directly present on the element, with no merging needed?
|
||||||
if (AnnotationFilter.PLAIN.matches(annotationType) ||
|
if (AnnotationFilter.PLAIN.matches(metaAnnotationType) ||
|
||||||
AnnotationFilter.PLAIN.matches(metaAnnotationType)) {
|
AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotationType)) {
|
||||||
return annotationType.isAnnotationPresent(metaAnnotationType);
|
return annotationType.isAnnotationPresent(metaAnnotationType);
|
||||||
}
|
}
|
||||||
// Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
|
|
||||||
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotationType)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Exhaustive retrieval of merged annotations...
|
// Exhaustive retrieval of merged annotations...
|
||||||
return (MergedAnnotations.from(
|
return MergedAnnotations.from(annotationType, SearchStrategy.INHERITED_ANNOTATIONS,
|
||||||
annotationType, SearchStrategy.INHERITED_ANNOTATIONS).isPresent(metaAnnotationType));
|
RepeatableContainers.none(), AnnotationFilter.PLAIN).isPresent(metaAnnotationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -40,7 +40,7 @@ import org.springframework.lang.Nullable;
|
||||||
*/
|
*/
|
||||||
final class TypeMappedAnnotations implements MergedAnnotations {
|
final class TypeMappedAnnotations implements MergedAnnotations {
|
||||||
|
|
||||||
private static final AnnotationFilter FILTER_ALL = annotationType -> true;
|
private static final AnnotationFilter FILTER_ALL = (annotationType -> true);
|
||||||
|
|
||||||
private static final MergedAnnotations NONE = new TypeMappedAnnotations(
|
private static final MergedAnnotations NONE = new TypeMappedAnnotations(
|
||||||
null, new Annotation[0], RepeatableContainers.none(), FILTER_ALL);
|
null, new Annotation[0], RepeatableContainers.none(), FILTER_ALL);
|
||||||
|
@ -108,8 +108,8 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A extends Annotation> boolean isDirectlyPresent(@Nullable Class<A> annotationType) {
|
public <A extends Annotation> boolean isDirectlyPresent(Class<A> annotationType) {
|
||||||
if (annotationType == null || this.annotationFilter.matches(annotationType)) {
|
if (this.annotationFilter.matches(annotationType)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return Boolean.TRUE.equals(scan(annotationType,
|
return Boolean.TRUE.equals(scan(annotationType,
|
||||||
|
@ -176,9 +176,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A extends Annotation> Stream<MergedAnnotation<A>> stream(
|
public <A extends Annotation> Stream<MergedAnnotation<A>> stream(Class<A> annotationType) {
|
||||||
@Nullable Class<A> annotationType) {
|
|
||||||
|
|
||||||
if (this.annotationFilter == FILTER_ALL) {
|
if (this.annotationFilter == FILTER_ALL) {
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
@ -186,9 +184,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <A extends Annotation> Stream<MergedAnnotation<A>> stream(
|
public <A extends Annotation> Stream<MergedAnnotation<A>> stream(String annotationType) {
|
||||||
@Nullable String annotationType) {
|
|
||||||
|
|
||||||
if (this.annotationFilter == FILTER_ALL) {
|
if (this.annotationFilter == FILTER_ALL) {
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
@ -219,8 +215,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||||
return spliterator(null);
|
return spliterator(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <A extends Annotation> Spliterator<MergedAnnotation<A>> spliterator(
|
private <A extends Annotation> Spliterator<MergedAnnotation<A>> spliterator(@Nullable Object annotationType) {
|
||||||
@Nullable Object annotationType) {
|
|
||||||
return new AggregatesSpliterator<>(annotationType, getAggregates());
|
return new AggregatesSpliterator<>(annotationType, getAggregates());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +243,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static MergedAnnotations from(@Nullable AnnotatedElement element, SearchStrategy searchStrategy,
|
static MergedAnnotations from(@Nullable AnnotatedElement element, SearchStrategy searchStrategy,
|
||||||
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
|
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.core.annotation;
|
package org.springframework.core.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Inherited;
|
import java.lang.annotation.Inherited;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
|
@ -28,6 +29,8 @@ import java.lang.reflect.Method;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
|
@ -36,6 +39,7 @@ import org.junit.Test;
|
||||||
import org.junit.internal.ArrayComparisonFailure;
|
import org.junit.internal.ArrayComparisonFailure;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
|
import org.springframework.lang.NonNullApi;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.stereotype.Indexed;
|
import org.springframework.stereotype.Indexed;
|
||||||
|
@ -121,33 +125,70 @@ public class AnnotatedElementUtilsTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAnnotatedOnNonAnnotatedClass() {
|
public void isAnnotatedOnNonAnnotatedClass() {
|
||||||
|
assertFalse(isAnnotated(NonAnnotatedClass.class, Transactional.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isAnnotatedOnClassWithMetaDepth() {
|
||||||
|
assertTrue(isAnnotated(TransactionalComponentClass.class, TransactionalComponent.class));
|
||||||
|
assertFalse("isAnnotated() does not search the class hierarchy.",
|
||||||
|
isAnnotated(SubTransactionalComponentClass.class, TransactionalComponent.class));
|
||||||
|
assertTrue(isAnnotated(TransactionalComponentClass.class, Transactional.class));
|
||||||
|
assertTrue(isAnnotated(TransactionalComponentClass.class, Component.class));
|
||||||
|
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, Transactional.class));
|
||||||
|
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, Component.class));
|
||||||
|
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isAnnotatedForPlainTypes() {
|
||||||
|
assertTrue(isAnnotated(Order.class, Documented.class));
|
||||||
|
assertTrue(isAnnotated(NonNullApi.class, Documented.class));
|
||||||
|
assertTrue(isAnnotated(NonNullApi.class, Nonnull.class));
|
||||||
|
assertTrue(isAnnotated(ParametersAreNonnullByDefault.class, Nonnull.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isAnnotatedWithNameOnNonAnnotatedClass() {
|
||||||
assertFalse(isAnnotated(NonAnnotatedClass.class, TX_NAME));
|
assertFalse(isAnnotated(NonAnnotatedClass.class, TX_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAnnotatedOnClassWithMetaDepth0() {
|
public void isAnnotatedWithNameOnClassWithMetaDepth() {
|
||||||
assertTrue(isAnnotated(TransactionalComponentClass.class, TransactionalComponent.class.getName()));
|
assertTrue(isAnnotated(TransactionalComponentClass.class, TransactionalComponent.class.getName()));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isAnnotatedOnSubclassWithMetaDepth0() {
|
|
||||||
assertFalse("isAnnotated() does not search the class hierarchy.",
|
assertFalse("isAnnotated() does not search the class hierarchy.",
|
||||||
isAnnotated(SubTransactionalComponentClass.class, TransactionalComponent.class.getName()));
|
isAnnotated(SubTransactionalComponentClass.class, TransactionalComponent.class.getName()));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isAnnotatedOnClassWithMetaDepth1() {
|
|
||||||
assertTrue(isAnnotated(TransactionalComponentClass.class, TX_NAME));
|
assertTrue(isAnnotated(TransactionalComponentClass.class, TX_NAME));
|
||||||
assertTrue(isAnnotated(TransactionalComponentClass.class, Component.class.getName()));
|
assertTrue(isAnnotated(TransactionalComponentClass.class, Component.class.getName()));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isAnnotatedOnClassWithMetaDepth2() {
|
|
||||||
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, TX_NAME));
|
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, TX_NAME));
|
||||||
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, Component.class.getName()));
|
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, Component.class.getName()));
|
||||||
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class.getName()));
|
assertTrue(isAnnotated(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasAnnotationOnNonAnnotatedClass() {
|
||||||
|
assertFalse(hasAnnotation(NonAnnotatedClass.class, Transactional.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasAnnotationOnClassWithMetaDepth() {
|
||||||
|
assertTrue(hasAnnotation(TransactionalComponentClass.class, TransactionalComponent.class));
|
||||||
|
assertTrue(hasAnnotation(SubTransactionalComponentClass.class, TransactionalComponent.class));
|
||||||
|
assertTrue(hasAnnotation(TransactionalComponentClass.class, Transactional.class));
|
||||||
|
assertTrue(hasAnnotation(TransactionalComponentClass.class, Component.class));
|
||||||
|
assertTrue(hasAnnotation(ComposedTransactionalComponentClass.class, Transactional.class));
|
||||||
|
assertTrue(hasAnnotation(ComposedTransactionalComponentClass.class, Component.class));
|
||||||
|
assertTrue(hasAnnotation(ComposedTransactionalComponentClass.class, ComposedTransactionalComponent.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasAnnotationForPlainTypes() {
|
||||||
|
assertTrue(hasAnnotation(Order.class, Documented.class));
|
||||||
|
assertTrue(hasAnnotation(NonNullApi.class, Documented.class));
|
||||||
|
assertTrue(hasAnnotation(NonNullApi.class, Nonnull.class));
|
||||||
|
assertTrue(hasAnnotation(ParametersAreNonnullByDefault.class, Nonnull.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAllAnnotationAttributesOnNonAnnotatedClass() {
|
public void getAllAnnotationAttributesOnNonAnnotatedClass() {
|
||||||
assertNull(getAllAnnotationAttributes(NonAnnotatedClass.class, TX_NAME));
|
assertNull(getAllAnnotationAttributes(NonAnnotatedClass.class, TX_NAME));
|
||||||
|
|
|
@ -18,7 +18,7 @@ package org.springframework.core.annotation;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Arrays;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -82,6 +82,11 @@ public class AnnotationFilterTests {
|
||||||
assertThat(AnnotationFilter.JAVA.matches(Retention.class)).isTrue();
|
assertThat(AnnotationFilter.JAVA.matches(Retention.class)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void javaWhenJavaxAnnotationReturnsTrue() {
|
||||||
|
assertThat(AnnotationFilter.JAVA.matches(Nonnull.class)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void javaWhenSpringLangAnnotationReturnsFalse() {
|
public void javaWhenSpringLangAnnotationReturnsFalse() {
|
||||||
assertThat(AnnotationFilter.JAVA.matches(Nullable.class)).isFalse();
|
assertThat(AnnotationFilter.JAVA.matches(Nullable.class)).isFalse();
|
||||||
|
|
|
@ -29,6 +29,8 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -438,9 +440,11 @@ public class AnnotationUtilsTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAnnotationMetaPresentForJavaLangType() {
|
public void isAnnotationMetaPresentForPlainType() {
|
||||||
assertTrue(isAnnotationMetaPresent(Order.class, Documented.class));
|
assertTrue(isAnnotationMetaPresent(Order.class, Documented.class));
|
||||||
assertTrue(isAnnotationMetaPresent(NonNullApi.class, Documented.class));
|
assertTrue(isAnnotationMetaPresent(NonNullApi.class, Documented.class));
|
||||||
|
assertTrue(isAnnotationMetaPresent(NonNullApi.class, Nonnull.class));
|
||||||
|
assertTrue(isAnnotationMetaPresent(ParametersAreNonnullByDefault.class, Nonnull.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue