From 5e15338a09b76c5ff2cc453edd34bfa38a865178 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 23 Mar 2019 12:13:38 +0100 Subject: [PATCH] Nullability refinements (no IntelliJ warnings, fewer null checks) Includes consistent ignoring of all java.lang (meta-)annotations. Closes gh-22586 --- .../annotation/AbstractMergedAnnotation.java | 3 +- .../annotation/AnnotatedElementUtils.java | 8 +- .../AnnotationAwareOrderComparator.java | 10 +- .../core/annotation/AnnotationFilter.java | 62 ++------ .../annotation/AnnotationTypeMapping.java | 2 +- .../annotation/AnnotationTypeMappings.java | 33 ++-- .../core/annotation/AnnotationUtils.java | 53 ++++--- .../core/annotation/AnnotationsProcessor.java | 5 +- .../core/annotation/AnnotationsScanner.java | 145 ++++++++--------- .../core/annotation/AttributeMethods.java | 44 +++--- .../IntrospectionFailureLogger.java | 11 +- .../core/annotation/MergedAnnotation.java | 60 ++++--- .../MergedAnnotationCollectors.java | 11 +- .../MergedAnnotationPredicates.java | 35 ++--- .../annotation/MergedAnnotationSelector.java | 3 +- .../annotation/MergedAnnotationSelectors.java | 10 +- .../core/annotation/MergedAnnotations.java | 55 +++---- .../annotation/MissingMergedAnnotation.java | 4 +- .../core/annotation/OrderUtils.java | 5 +- .../annotation/PackagesAnnotationFilter.java | 27 ++-- .../core/annotation/RepeatableContainers.java | 34 ++-- ...izedMergedAnnotationInvocationHandler.java | 43 ++--- .../core/annotation/TypeMappedAnnotation.java | 55 +++---- .../annotation/TypeMappedAnnotations.java | 148 +++++++----------- .../util/ConcurrentReferenceHashMap.java | 4 +- .../AnnotatedElementUtilsTests.java | 13 +- .../annotation/AnnotationFilterTests.java | 59 ++----- .../AnnotationTypeMappingsTests.java | 38 ++--- .../core/annotation/AnnotationUtilsTests.java | 7 - .../annotation/AnnotationsScannerTests.java | 102 ++++-------- .../MergedAnnotationCollectorsTests.java | 18 +-- .../MergedAnnotationPredicatesTests.java | 70 ++------- .../annotation/MergedAnnotationsTests.java | 63 ++------ 33 files changed, 439 insertions(+), 801 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AbstractMergedAnnotation.java b/spring-core/src/main/java/org/springframework/core/annotation/AbstractMergedAnnotation.java index 0edb680031b8..a28e48631978 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AbstractMergedAnnotation.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AbstractMergedAnnotation.java @@ -33,8 +33,7 @@ * @since 5.2 * @param the annotation type */ -abstract class AbstractMergedAnnotation - implements MergedAnnotation { +abstract class AbstractMergedAnnotation implements MergedAnnotation { @Nullable private volatile A synthesizedAnnotation; diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java index b58af393ca62..5e3eb8f86ea5 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java @@ -828,13 +828,13 @@ private static Comparator> highAggreg } @Nullable - private static AnnotationAttributes getAnnotationAttributes( - MergedAnnotation annotation, boolean classValuesAsString, - boolean nestedAnnotationsAsMap) { + private static AnnotationAttributes getAnnotationAttributes(MergedAnnotation annotation, + boolean classValuesAsString, boolean nestedAnnotationsAsMap) { + if (!annotation.isPresent()) { return null; } - return annotation.asMap((mergedAnnotation) -> new AnnotationAttributes(), + return annotation.asMap(mergedAnnotation -> new AnnotationAttributes(), MapValues.of(classValuesAsString, nestedAnnotationsAsMap)); } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java index 79bf0716921a..3f05ca973597 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationAwareOrderComparator.java @@ -68,14 +68,12 @@ protected Integer findOrder(Object obj) { return findOrderFromAnnotation(obj); } + @Nullable private Integer findOrderFromAnnotation(Object obj) { - AnnotatedElement element = obj instanceof AnnotatedElement - ? (AnnotatedElement) obj - : obj.getClass(); - MergedAnnotations annotations = MergedAnnotations.from(element, - SearchStrategy.EXHAUSTIVE); + AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass()); + MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.EXHAUSTIVE); Integer order = OrderUtils.getOrderFromAnnotations(element, annotations); - if (order == null && obj instanceof DecoratingProxy) { + if (order == null && obj instanceof DecoratingProxy) { return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass()); } return order; diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationFilter.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationFilter.java index be2fb4b2b158..18ac08a4dcd8 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationFilter.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationFilter.java @@ -20,7 +20,6 @@ import java.util.Arrays; import java.util.Collection; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; /** @@ -37,31 +36,27 @@ public interface AnnotationFilter { * {@code java.lang.*} or in the * {@code org.springframework.lang.*} package. */ - static final AnnotationFilter PLAIN = packages("java.lang", - "org.springframework.lang"); + AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang"); /** * {@link AnnotationFilter} that matches annotations in the * {@code java.lang.*} package. */ - static final AnnotationFilter JAVA = packages("java.lang"); + AnnotationFilter JAVA = packages("java.lang"); /** * {@link AnnotationFilter} that never matches and can be used when no * filtering is needed. */ - static final AnnotationFilter NONE = new AnnotationFilter() { - + AnnotationFilter NONE = new AnnotationFilter() { @Override - public boolean matches(@Nullable String typeName) { + public boolean matches(String typeName) { return false; } - @Override public String toString() { return "No annotation filtering"; } - }; @@ -70,8 +65,8 @@ public String toString() { * @param annotation the annotation to test * @return {@code true} if the annotation matches */ - default boolean matches(@Nullable Annotation annotation) { - return matches(annotation != null ? annotation.annotationType() : null); + default boolean matches(Annotation annotation) { + return matches(annotation.annotationType()); } /** @@ -79,8 +74,8 @@ default boolean matches(@Nullable Annotation annotation) { * @param type the annotation type to test * @return {@code true} if the annotation matches */ - default boolean matches(@Nullable Class type) { - return matches(type != null ? type.getName() : null); + default boolean matches(Class type) { + return matches(type.getName()); } /** @@ -88,7 +83,8 @@ default boolean matches(@Nullable Class type) { * @param typeName the annotation type to test * @return {@code true} if the annotation matches */ - boolean matches(@Nullable String typeName); + boolean matches(String typeName); + /** * Return a new {@link AnnotationFilter} that matches annotations in the @@ -107,8 +103,8 @@ static AnnotationFilter packages(String... packages) { * @param annotationType the annotation type to check * @return the most appropriate annotation filter */ - static AnnotationFilter mostAppropriateFor(@Nullable Class annotationType) { - return PLAIN.matches(annotationType) ? NONE : PLAIN; + static AnnotationFilter mostAppropriateFor(Class annotationType) { + return (PLAIN.matches(annotationType) ? NONE : PLAIN); } /** @@ -119,30 +115,6 @@ static AnnotationFilter mostAppropriateFor(@Nullable Class annotationType) { * @return the most appropriate annotation filter */ static AnnotationFilter mostAppropriateFor(Class... annotationTypes) { - Assert.notNull(annotationTypes, "AnnotationTypes must not be null"); - return mostAppropriateFor(Arrays.asList(annotationTypes)); - } - - /** - * Return an {@link AnnotationFilter} that is the most appropriate for, and - * will always match all the given annotation type. Whenever possible, - * {@link AnnotationFilter#PLAIN} will be returned. - * @param annotationType the annotation type to check - * @return the most appropriate annotation filter - */ - static AnnotationFilter mostAppropriateFor(@Nullable String annotationType) { - return PLAIN.matches(annotationType) ? NONE : PLAIN; - } - - /** - * Return an {@link AnnotationFilter} that is the most appropriate for, and - * will always match all the given annotation types. Whenever possible, - * {@link AnnotationFilter#PLAIN} will be returned. - * @param annotationTypes the annotation types to check - * @return the most appropriate annotation filter - */ - static AnnotationFilter mostAppropriateFor(String... annotationTypes) { - Assert.notNull(annotationTypes, "AnnotationTypes must not be null"); return mostAppropriateFor(Arrays.asList(annotationTypes)); } @@ -156,20 +128,16 @@ static AnnotationFilter mostAppropriateFor(String... annotationTypes) { */ @SuppressWarnings("unchecked") static AnnotationFilter mostAppropriateFor(Collection annotationTypes) { - Assert.notNull(annotationTypes, "AnnotationTypes must not be null"); for (Object annotationType : annotationTypes) { if (annotationType == null) { continue; } - Assert.isTrue( - annotationType instanceof Class || annotationType instanceof String, + Assert.isTrue(annotationType instanceof Class || annotationType instanceof String, "AnnotationType must be a Class or String"); - if (annotationType instanceof Class - && PLAIN.matches((Class) annotationType)) { + if (annotationType instanceof Class && PLAIN.matches((Class) annotationType)) { return NONE; } - if (annotationType instanceof String - && PLAIN.matches((String) annotationType)) { + if (annotationType instanceof String && PLAIN.matches((String) annotationType)) { return NONE; } } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java index f45ecac45f1c..64b6e7727b88 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java @@ -45,7 +45,7 @@ * @since 5.2 * @see AnnotationTypeMappings */ -class AnnotationTypeMapping { +final class AnnotationTypeMapping { @Nullable private final AnnotationTypeMapping parent; diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMappings.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMappings.java index eae514147132..f217ef446f41 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMappings.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMappings.java @@ -24,7 +24,6 @@ import java.util.Map; import org.springframework.lang.Nullable; -import org.springframework.util.Assert; import org.springframework.util.ConcurrentReferenceHashMap; /** @@ -75,11 +74,9 @@ private void addAllMappings(Class annotationType) { } } - private void addMetaAnnotationsToQueue(Deque queue, - AnnotationTypeMapping parent) { - - Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations( - parent.getAnnotationType(), false); + private void addMetaAnnotationsToQueue(Deque queue, AnnotationTypeMapping parent) { + Annotation[] metaAnnotations = + AnnotationsScanner.getDeclaredAnnotations(parent.getAnnotationType(), false); for (Annotation metaAnnotation : metaAnnotations) { if (!isMappable(parent, metaAnnotation)) { continue; @@ -125,19 +122,17 @@ private void addIfPossible(Deque queue, } } - private boolean isMappable(AnnotationTypeMapping parent, Annotation metaAnnotation) { - return !this.filter.matches(metaAnnotation) && + private boolean isMappable(AnnotationTypeMapping parent, @Nullable Annotation metaAnnotation) { + return (metaAnnotation != null && !this.filter.matches(metaAnnotation) && !AnnotationFilter.PLAIN.matches(parent.getAnnotationType()) && - !isAlreadyMapped(parent, metaAnnotation); + !isAlreadyMapped(parent, metaAnnotation)); } - private boolean isAlreadyMapped(AnnotationTypeMapping parent, - Annotation metaAnnotation) { - + private boolean isAlreadyMapped(AnnotationTypeMapping parent, Annotation metaAnnotation) { Class annotationType = metaAnnotation.annotationType(); AnnotationTypeMapping mapping = parent; while (mapping != null) { - if (mapping.getAnnotationType().equals(annotationType)) { + if (mapping.getAnnotationType() == annotationType) { return true; } mapping = mapping.getParent(); @@ -171,11 +166,8 @@ AnnotationTypeMapping get(int index) { * @param annotationType the source annotation type * @return type mappings for the annotation type */ - static AnnotationTypeMappings forAnnotationType( - Class annotationType) { - - return forAnnotationType(annotationType, - AnnotationFilter.mostAppropriateFor(annotationType)); + static AnnotationTypeMappings forAnnotationType(Class annotationType) { + return forAnnotationType(annotationType, AnnotationFilter.mostAppropriateFor(annotationType)); } /** @@ -186,11 +178,8 @@ static AnnotationTypeMappings forAnnotationType( * @return type mappings for the annotation type */ static AnnotationTypeMappings forAnnotationType( - Class annotationType, - AnnotationFilter annotationFilter) { + Class annotationType, AnnotationFilter annotationFilter) { - Assert.notNull(annotationType, "AnnotationType must not be null"); - Assert.notNull(annotationFilter, "AnnotationFilter must not be null"); return cache.computeIfAbsent(annotationFilter, Cache::new).get(annotationType); } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index 377d2eb578c1..b79e18d2a065 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -477,8 +477,10 @@ public static A findAnnotation( * @see #getAnnotation(Method, Class) */ @Nullable - public static A findAnnotation(Method method, - @Nullable Class annotationType) { + public static A findAnnotation(Method method, @Nullable Class annotationType) { + if (annotationType == null) { + return null; + } AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationType); return MergedAnnotations.from(method, SearchStrategy.EXHAUSTIVE, @@ -510,9 +512,7 @@ public static A findAnnotation(Method method, * @return the first matching annotation, or {@code null} if not found */ @Nullable - public static A findAnnotation(Class clazz, - Class annotationType) { - + public static A findAnnotation(Class clazz, Class annotationType) { AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationType); return MergedAnnotations.from(clazz, SearchStrategy.EXHAUSTIVE, RepeatableContainers.none(), annotationFilter) @@ -535,8 +535,8 @@ public static A findAnnotation(Class clazz, * @param annotationType the annotation type to look for * @param clazz the class to check for the annotation on (may be {@code null}) * @return the first {@link Class} in the inheritance hierarchy that - * declares an annotation of the specified {@code annotationType}, or - * {@code null} if not found + * declares an annotation of the specified {@code annotationType}, + * or {@code null} if not found * @see Class#isAnnotationPresent(Class) * @see Class#getDeclaredAnnotations() * @see #findAnnotationDeclaringClassForTypes(List, Class) @@ -546,6 +546,10 @@ public static A findAnnotation(Class clazz, public static Class findAnnotationDeclaringClass( Class annotationType, @Nullable Class clazz) { + if (clazz == null) { + return null; + } + AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationType); return (Class) MergedAnnotations.from(clazz, SearchStrategy.SUPER_CLASS, RepeatableContainers.none(), annotationFilter) @@ -567,7 +571,7 @@ public static Class findAnnotationDeclaringClass( * one of several candidate {@linkplain Annotation annotations}, so we * need to handle this explicitly. * @param annotationTypes the annotation types to look for - * @param clazz the class to check for the annotations on, or {@code null} + * @param clazz the class to check for the annotation on (may be {@code null}) * @return the first {@link Class} in the inheritance hierarchy that * declares an annotation of at least one of the specified * {@code annotationTypes}, or {@code null} if not found @@ -581,6 +585,10 @@ public static Class findAnnotationDeclaringClass( public static Class findAnnotationDeclaringClassForTypes( List> annotationTypes, @Nullable Class clazz) { + if (clazz == null) { + return null; + } + AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationTypes); return (Class) MergedAnnotations.from(clazz, SearchStrategy.SUPER_CLASS, RepeatableContainers.none(), annotationFilter) @@ -608,9 +616,7 @@ public static Class findAnnotationDeclaringClassForTypes( * @see java.lang.Class#getDeclaredAnnotation(Class) * @see #isAnnotationInherited(Class, Class) */ - public static boolean isAnnotationDeclaredLocally( - Class annotationType, Class clazz) { - + public static boolean isAnnotationDeclaredLocally(Class annotationType, Class clazz) { return MergedAnnotations.from(clazz).get(annotationType).isDirectlyPresent(); } @@ -633,9 +639,7 @@ public static boolean isAnnotationDeclaredLocally( * @see Class#isAnnotationPresent(Class) * @see #isAnnotationDeclaredLocally(Class, Class) */ - public static boolean isAnnotationInherited( - Class annotationType, Class clazz) { - + public static boolean isAnnotationInherited(Class annotationType, Class clazz) { return MergedAnnotations.from(clazz, SearchStrategy.INHERITED_ANNOTATIONS) .stream(annotationType) .filter(MergedAnnotation::isDirectlyPresent) @@ -651,12 +655,10 @@ public static boolean isAnnotationInherited( * @return {@code true} if such an annotation is meta-present * @since 4.2.1 */ - public static boolean isAnnotationMetaPresent( - Class annotationType, + public static boolean isAnnotationMetaPresent(Class annotationType, @Nullable Class metaAnnotationType) { - return MergedAnnotations.from(annotationType, SearchStrategy.EXHAUSTIVE) - .isPresent(annotationType); + return MergedAnnotations.from(annotationType, SearchStrategy.EXHAUSTIVE).isPresent(annotationType); } /** @@ -666,7 +668,7 @@ public static boolean isAnnotationMetaPresent( * @return {@code true} if the annotation is in the {@code java.lang.annotation} package */ public static boolean isInJavaLangAnnotationPackage(@Nullable Annotation annotation) { - return JAVA_LANG_ANNOTATION_FILTER.matches(annotation); + return (annotation != null && JAVA_LANG_ANNOTATION_FILTER.matches(annotation)); } /** @@ -677,7 +679,7 @@ public static boolean isInJavaLangAnnotationPackage(@Nullable Annotation annotat * @since 4.2 */ public static boolean isInJavaLangAnnotationPackage(@Nullable String annotationType) { - return JAVA_LANG_ANNOTATION_FILTER.matches(annotationType); + return (annotationType != null && JAVA_LANG_ANNOTATION_FILTER.matches(annotationType)); } /** @@ -693,8 +695,7 @@ public static boolean isInJavaLangAnnotationPackage(@Nullable String annotationT * @see #getAnnotationAttributes(Annotation) */ public static void validateAnnotation(Annotation annotation) { - AttributeMethods.forAnnotationType(annotation.annotationType()) - .validate(annotation); + AttributeMethods.forAnnotationType(annotation.annotationType()).validate(annotation); } /** @@ -889,13 +890,15 @@ private static Map computeDefaultValues( public static void postProcessAnnotationAttributes(@Nullable Object annotatedElement, @Nullable AnnotationAttributes attributes, boolean classValuesAsString) { - if (attributes == null || attributes.annotationType() == null) { + if (attributes == null) { return; } if (!attributes.validated) { Class annotationType = attributes.annotationType(); - AnnotationTypeMapping mapping = AnnotationTypeMappings - .forAnnotationType(annotationType).get(0); + if (annotationType == null) { + return; + } + AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0); for (int i = 0; i < mapping.getMirrorSets().size(); i++) { MirrorSet mirrorSet = mapping.getMirrorSets().get(i); int resolved = mirrorSet.resolve(attributes.displayName, attributes, diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsProcessor.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsProcessor.java index 19b2e01d57c8..c2e4950435bd 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsProcessor.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsProcessor.java @@ -55,13 +55,12 @@ default R doWithAggregate(C context, int aggregateIndex) { * @return a {@code non-null} result if no further processing is required */ @Nullable - R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source, - Annotation[] annotations); + R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source, Annotation[] annotations); /** * Return the final result to be returned. By default this method returns * the last process result. - * @param result the last early exit result, or {@code null}. + * @param result the last early exit result, or {@code null} if none * @return the final result to be returned to the caller */ @Nullable diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java index 608d9890d0e8..e2598eba1d54 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java @@ -71,8 +71,9 @@ private AnnotationsScanner() { * @return the result of {@link AnnotationsProcessor#finish(Object)} */ @Nullable - static R scan(C context, AnnotatedElement source, - SearchStrategy searchStrategy, AnnotationsProcessor processor) { + static R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy, + AnnotationsProcessor processor) { + return scan(context, source, searchStrategy, processor, null); } @@ -89,9 +90,8 @@ static R scan(C context, AnnotatedElement source, * @return the result of {@link AnnotationsProcessor#finish(Object)} */ @Nullable - static R scan(C context, AnnotatedElement source, - SearchStrategy searchStrategy, AnnotationsProcessor processor, - @Nullable BiPredicate> classFilter) { + static R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy, + AnnotationsProcessor processor, @Nullable BiPredicate> classFilter) { R result = process(context, source, searchStrategy, processor, classFilter); return processor.finish(result); @@ -135,8 +135,7 @@ private static R processClass(C context, Class source, @Nullable private static R processClassInheritedAnnotations(C context, Class source, - AnnotationsProcessor processor, - @Nullable BiPredicate> classFilter) { + AnnotationsProcessor processor, @Nullable BiPredicate> classFilter) { if (isWithoutHierarchy(source)) { return processElement(context, source, processor, classFilter); @@ -145,8 +144,8 @@ private static R processClassInheritedAnnotations(C context, Class sou int remaining = Integer.MAX_VALUE; int aggregateIndex = 0; Class root = source; - while (source != null && source != Object.class && remaining > 0 - && !hasPlainJavaAnnotationsOnly(source)) { + while (source != null && source != Object.class && remaining > 0 && + !hasPlainJavaAnnotationsOnly(source)) { R result = processor.doWithAggregate(context, aggregateIndex); if (result != null) { return result; @@ -208,7 +207,7 @@ private static R processClassHierarchy(C context, int[] aggregateIndex, if (includeInterfaces) { for (Class interfaceType : source.getInterfaces()) { R interfacesResult = processClassHierarchy(context, aggregateIndex, - interfaceType, processor, classFilter, includeInterfaces); + interfaceType, processor, classFilter, true); if (interfacesResult != null) { return interfacesResult; } @@ -233,13 +232,12 @@ private static R processMethod(C context, Method source, switch (searchStrategy) { case DIRECT: case INHERITED_ANNOTATIONS: - return processMethodInheritedAnnotations(context, source, - processor, classFilter); + return processMethodInheritedAnnotations(context, source, processor, classFilter); case SUPER_CLASS: - return processMethodHierarchy(context, new int[] { 0 }, source.getDeclaringClass(), + return processMethodHierarchy(context, new int[] {0}, source.getDeclaringClass(), processor, classFilter, source, false); case EXHAUSTIVE: - return processMethodHierarchy(context, new int[] { 0 }, source.getDeclaringClass(), + return processMethodHierarchy(context, new int[] {0}, source.getDeclaringClass(), processor, classFilter, source, true); } throw new IllegalStateException("Unsupported search strategy " + searchStrategy); @@ -247,12 +245,11 @@ private static R processMethod(C context, Method source, @Nullable private static R processMethodInheritedAnnotations(C context, Method source, - AnnotationsProcessor processor, - @Nullable BiPredicate> classFilter) { + AnnotationsProcessor processor, @Nullable BiPredicate> classFilter) { R result = processor.doWithAggregate(context, 0); - return result != null ? result : - processMethodAnnotations(context, 0, source, processor, classFilter); + return (result != null ? result : + processMethodAnnotations(context, 0, source, processor, classFilter)); } @Nullable @@ -298,7 +295,7 @@ private static R processMethodHierarchy(C context, int[] aggregateIndex, if (includeInterfaces) { for (Class interfaceType : sourceClass.getInterfaces()) { R interfacesResult = processMethodHierarchy(context, aggregateIndex, - interfaceType, processor, classFilter, rootMethod, includeInterfaces); + interfaceType, processor, classFilter, rootMethod, true); if (interfacesResult != null) { return interfacesResult; } @@ -315,8 +312,8 @@ private static R processMethodHierarchy(C context, int[] aggregateIndex, return null; } - private static Method[] getBaseTypeMethods(C context, Class baseType, - @Nullable BiPredicate> classFilter) { + private static Method[] getBaseTypeMethods( + C context, Class baseType, @Nullable BiPredicate> classFilter) { if (baseType == Object.class || hasPlainJavaAnnotationsOnly(baseType) || isFiltered(baseType, context, classFilter)) { @@ -326,8 +323,7 @@ private static Method[] getBaseTypeMethods(C context, Class baseType, Method[] methods = baseTypeMethodsCache.get(baseType); if (methods == null) { boolean isInterface = baseType.isInterface(); - methods = isInterface ? baseType.getMethods() - : ReflectionUtils.getDeclaredMethods(baseType); + methods = isInterface ? baseType.getMethods() : ReflectionUtils.getDeclaredMethods(baseType); int cleared = 0; for (int i = 0; i < methods.length; i++) { if ((!isInterface && Modifier.isPrivate(methods[i].getModifiers())) || @@ -346,14 +342,12 @@ private static Method[] getBaseTypeMethods(C context, Class baseType, } private static boolean isOverride(Method rootMethod, Method candidateMethod) { - return !Modifier.isPrivate(candidateMethod.getModifiers()) && + return (!Modifier.isPrivate(candidateMethod.getModifiers()) && candidateMethod.getName().equals(rootMethod.getName()) && - hasSameParameterTypes(rootMethod, candidateMethod); + hasSameParameterTypes(rootMethod, candidateMethod)); } - private static boolean hasSameParameterTypes(Method rootMethod, - Method candidateMethod) { - + private static boolean hasSameParameterTypes(Method rootMethod, Method candidateMethod) { if (candidateMethod.getParameterCount() != rootMethod.getParameterCount()) { return false; } @@ -366,8 +360,8 @@ private static boolean hasSameParameterTypes(Method rootMethod, rootParameterTypes); } - private static boolean hasSameGenericTypeParameters(Method rootMethod, - Method candidateMethod, Class[] rootParameterTypes) { + private static boolean hasSameGenericTypeParameters( + Method rootMethod, Method candidateMethod, Class[] rootParameterTypes) { Class sourceDeclaringClass = rootMethod.getDeclaringClass(); Class candidateDeclaringClass = candidateMethod.getDeclaringClass(); @@ -385,53 +379,43 @@ private static boolean hasSameGenericTypeParameters(Method rootMethod, } @Nullable - private static R processMethodAnnotations(C context, int aggregateIndex, - Method source, AnnotationsProcessor processor, - @Nullable BiPredicate> classFilter) { + private static R processMethodAnnotations(C context, int aggregateIndex, Method source, + AnnotationsProcessor processor, @Nullable BiPredicate> classFilter) { - Annotation[] annotations = getDeclaredAnnotations(context, source, classFilter, - false); - R result = processor.doWithAnnotations(context, aggregateIndex, source, - annotations); + Annotation[] annotations = getDeclaredAnnotations(context, source, classFilter, false); + R result = processor.doWithAnnotations(context, aggregateIndex, source, annotations); if (result != null) { return result; } Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(source); if (bridgedMethod != source) { - Annotation[] bridgedAnnotations = getDeclaredAnnotations(context, - bridgedMethod, classFilter, true); + Annotation[] bridgedAnnotations = getDeclaredAnnotations(context, bridgedMethod, classFilter, true); for (int i = 0; i < bridgedAnnotations.length; i++) { if (ObjectUtils.containsElement(annotations, bridgedAnnotations[i])) { bridgedAnnotations[i] = null; } } - return processor.doWithAnnotations(context, aggregateIndex, source, - bridgedAnnotations); + return processor.doWithAnnotations(context, aggregateIndex, source, bridgedAnnotations); } return null; } @Nullable private static R processElement(C context, AnnotatedElement source, - AnnotationsProcessor processor, - @Nullable BiPredicate> classFilter) { + AnnotationsProcessor processor, @Nullable BiPredicate> classFilter) { R result = processor.doWithAggregate(context, 0); - return result != null ? result - : processor.doWithAnnotations(context, 0, source, - getDeclaredAnnotations(context, source, classFilter, false)); + return (result != null ? result : processor.doWithAnnotations(context, 0, source, + getDeclaredAnnotations(context, source, classFilter, false))); } private static Annotation[] getDeclaredAnnotations(C context, - AnnotatedElement source, @Nullable BiPredicate> classFilter, - boolean copy) { + AnnotatedElement source, @Nullable BiPredicate> classFilter, boolean copy) { - if (source instanceof Class && - isFiltered((Class) source, context, classFilter)) { + if (source instanceof Class && isFiltered((Class) source, context, classFilter)) { return NO_ANNOTATIONS; } - if (source instanceof Method && - isFiltered(((Method) source).getDeclaringClass(), context, classFilter)) { + if (source instanceof Method && isFiltered(((Method) source).getDeclaringClass(), context, classFilter)) { return NO_ANNOTATIONS; } return getDeclaredAnnotations(source, copy); @@ -439,40 +423,37 @@ private static Annotation[] getDeclaredAnnotations(C context, @SuppressWarnings("unchecked") @Nullable - static A getDeclaredAnnotation(AnnotatedElement source, - Class annotationType) { - + static A getDeclaredAnnotation(AnnotatedElement source, Class annotationType) { Annotation[] annotations = getDeclaredAnnotations(source, false); - for (int i = 0; i < annotations.length; i++) { - if (annotations[i] != null && - annotationType.equals(annotations[i].annotationType())) { - return (A) annotations[i]; + for (Annotation annotation : annotations) { + if (annotation != null && annotationType.equals(annotation.annotationType())) { + return (A) annotation; } } return null; } - static Annotation[] getDeclaredAnnotations(AnnotatedElement source, - boolean defensive) { - - boolean cached = true; + static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) { + boolean cached = false; Annotation[] annotations = declaredAnnotationCache.get(source); - if (annotations == null) { + if (annotations != null) { + cached = true; + } + else { annotations = source.getDeclaredAnnotations(); if (annotations.length != 0) { boolean allIgnored = true; for (int i = 0; i < annotations.length; i++) { Annotation annotation = annotations[i]; if (isIgnorable(annotation.annotationType()) || - !AttributeMethods.forAnnotationType( - annotation.annotationType()).isValid(annotation)) { + !AttributeMethods.forAnnotationType(annotation.annotationType()).isValid(annotation)) { annotations[i] = null; } else { allIgnored = false; } } - annotations = allIgnored ? NO_ANNOTATIONS : annotations; + annotations = (allIgnored ? NO_ANNOTATIONS : annotations); if (source instanceof Class || source instanceof Member) { declaredAnnotationCache.put(source, annotations); cached = true; @@ -486,19 +467,17 @@ static Annotation[] getDeclaredAnnotations(AnnotatedElement source, } private static boolean isIgnorable(Class annotationType) { - return (annotationType == Nullable.class || - annotationType == FunctionalInterface.class); + return AnnotationFilter.PLAIN.matches(annotationType); } - private static boolean isFiltered(Class sourceClass, C context, - @Nullable BiPredicate> classFilter) { - return classFilter != null && classFilter.test(context, sourceClass); + private static boolean isFiltered( + Class sourceClass, C context, @Nullable BiPredicate> classFilter) { + + return (classFilter != null && classFilter.test(context, sourceClass)); } - static boolean isKnownEmpty(AnnotatedElement source, - SearchStrategy searchStrategy, AnnotationFilter annotationFilter) { - if (annotationFilter == AnnotationFilter.PLAIN && - hasPlainJavaAnnotationsOnly(source)) { + static boolean isKnownEmpty(AnnotatedElement source,SearchStrategy searchStrategy, AnnotationFilter annotationFilter) { + if (annotationFilter == AnnotationFilter.PLAIN && hasPlainJavaAnnotationsOnly(source)) { return true; } if (searchStrategy == SearchStrategy.DIRECT || isWithoutHierarchy(source)) { @@ -511,7 +490,7 @@ static boolean isKnownEmpty(AnnotatedElement source, } static boolean hasPlainJavaAnnotationsOnly(@Nullable Object annotatedElement) { - Class type = null; + Class type; if (annotatedElement instanceof Class) { type = (Class) annotatedElement; } @@ -522,11 +501,11 @@ else if (annotatedElement instanceof Member) { return false; } String name = type.getName(); - return type.equals(Ordered.class) || + return (type == Ordered.class || name.startsWith("java") || name.startsWith("org.springframework.lang.") || name.startsWith("org.springframework.util.") || - (name.startsWith("com.sun") && !name.contains("Proxy")); + (name.startsWith("com.sun") && !name.contains("Proxy"))); } private static boolean isWithoutHierarchy(AnnotatedElement source) { @@ -535,13 +514,13 @@ private static boolean isWithoutHierarchy(AnnotatedElement source) { } if (source instanceof Class) { Class sourceClass = (Class) source; - return sourceClass.getSuperclass() == Object.class && - sourceClass.getInterfaces().length == 0; + return (sourceClass.getSuperclass() == Object.class && + sourceClass.getInterfaces().length == 0); } if (source instanceof Method) { Method sourceMethod = (Method) source; - return Modifier.isPrivate(sourceMethod.getModifiers()) || - isWithoutHierarchy(sourceMethod.getDeclaringClass()); + return (Modifier.isPrivate(sourceMethod.getModifiers()) || + isWithoutHierarchy(sourceMethod.getDeclaringClass())); } return true; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java b/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java index 6f5f9ef53c99..2fd9273eebef 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AttributeMethods.java @@ -48,6 +48,7 @@ final class AttributeMethods { return m1 != null ? -1 : 1; }; + @Nullable private final Class annotationType; @@ -60,8 +61,7 @@ final class AttributeMethods { private final boolean hasNestedAnnotation; - private AttributeMethods(@Nullable Class annotationType, - Method[] attributeMethods) { + private AttributeMethods(@Nullable Class annotationType, Method[] attributeMethods) { this.annotationType = annotationType; this.attributeMethods = attributeMethods; this.canThrowTypeNotPresentException = new boolean[attributeMethods.length]; @@ -94,8 +94,8 @@ private AttributeMethods(@Nullable Class annotationType, * @return {@code true} if this is only a value attribute */ boolean isOnlyValueAttribute() { - return this.attributeMethods.length == 1 && - MergedAnnotation.VALUE.equals(this.attributeMethods[0].getName()); + return (this.attributeMethods.length == 1 && + MergedAnnotation.VALUE.equals(this.attributeMethods[0].getName())); } @@ -104,7 +104,7 @@ boolean isOnlyValueAttribute() { * accessed without causing any {@link TypeNotPresentException * TypeNotPresentExceptions}. * @param annotation the annotation to check - * @return {@true} if all values are present + * @return {@code true} if all values are present * @see #validate(Annotation) */ boolean isValid(Annotation annotation) { @@ -123,14 +123,13 @@ boolean isValid(Annotation annotation) { } /** - * Checks if values from the given annotation can be safely accessed without - * causing any {@link TypeNotPresentException TypeNotPresentExceptions}. In - * particular, this method is designed to cover Google App Engine's late - * arrival of such exceptions for {@code Class} values (instead of the more - * typical early {@code Class.getAnnotations() failure}. + * Checks if values from the given annotation can be safely accessed without causing + * any {@link TypeNotPresentException TypeNotPresentExceptions}. In particular, + * this method is designed to cover Google App Engine's late arrival of such + * exceptions for {@code Class} values (instead of the more typical early + * {@code Class.getAnnotations() failure}. * @param annotation the annotation to validate - * @throws IllegalStateException if a declared {@code Class} attribute could - * not be read + * @throws IllegalStateException if a declared {@code Class} attribute could not be read * @see #isValid(Annotation) */ void validate(Annotation annotation) { @@ -141,11 +140,8 @@ void validate(Annotation annotation) { get(i).invoke(annotation); } catch (Throwable ex) { - throw new IllegalStateException( - "Could not obtain annotation attribute value for " - + get(i).getName() + " declared on " - + annotation.annotationType(), - ex); + throw new IllegalStateException("Could not obtain annotation attribute value for " + + get(i).getName() + " declared on " + annotation.annotationType(), ex); } } } @@ -246,14 +242,13 @@ boolean hasNestedAnnotation() { return this.hasNestedAnnotation; } + /** * Return the attribute methods for the given annotation type. * @param annotationType the annotation type * @return the attribute methods for the annotation */ - static AttributeMethods forAnnotationType( - @Nullable Class annotationType) { - + static AttributeMethods forAnnotationType(@Nullable Class annotationType) { if (annotationType == null) { return NONE; } @@ -279,7 +274,7 @@ private static AttributeMethods compute(Class annotationTy } private static boolean isAttributeMethod(Method method) { - return method.getParameterCount() == 0 && method.getReturnType() != void.class; + return (method.getParameterCount() == 0 && method.getReturnType() != void.class); } /** @@ -302,14 +297,11 @@ static String describe(@Nullable Method attribute) { * @param attributeName the attribute name * @return a description of the attribute */ - static String describe(@Nullable Class annotationType, - @Nullable String attributeName) { + static String describe(@Nullable Class annotationType, @Nullable String attributeName) { if (attributeName == null) { return "(none)"; } - String in = annotationType != null ? - " in annotation [" + annotationType.getName() + "]" : - ""; + String in = (annotationType != null ? " in annotation [" + annotationType.getName() + "]" : ""); return "attribute '" + attributeName + "'" + in; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/IntrospectionFailureLogger.java b/spring-core/src/main/java/org/springframework/core/annotation/IntrospectionFailureLogger.java index 08f3f79e4d10..c1c3d4c49072 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/IntrospectionFailureLogger.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/IntrospectionFailureLogger.java @@ -33,12 +33,10 @@ enum IntrospectionFailureLogger { DEBUG { - @Override public boolean isEnabled() { return getLogger().isDebugEnabled(); } - @Override public void log(String message) { getLogger().debug(message); @@ -46,12 +44,10 @@ public void log(String message) { }, INFO { - @Override public boolean isEnabled() { return getLogger().isInfoEnabled(); } - @Override public void log(String message) { getLogger().info(message); @@ -63,15 +59,16 @@ public void log(String message) { private static Log logger; - abstract boolean isEnabled(); - void log(String message, @Nullable Object source, Exception ex) { - String on = source != null ? " on " + source : ""; + String on = (source != null ? " on " + source : ""); log(message + on + ": " + ex); } + abstract boolean isEnabled(); + abstract void log(String message); + private static Log getLogger() { Log logger = IntrospectionFailureLogger.logger; if (logger == null) { diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java index 6984b03b846c..7a1265226f56 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java @@ -40,8 +40,8 @@ * For example, to access an {@code int} attribute the {@link #getInt(String)} * method would be used. * - *

Note that attribute values are not converted when accessed. For - * example, it is not possible to call {@link #getString(String)} if the + *

Note that attribute values are not converted when accessed. + * For example, it is not possible to call {@link #getString(String)} if the * underlying attribute is an {@code int}. The only exception to this rule is * {@code Class} and {@code Class[]} values which may be accessed as * {@code String} and {@code String[]} respectively to prevent potential early @@ -63,6 +63,7 @@ public interface MergedAnnotation { */ String VALUE = "value"; + /** * Return the class name of the actual annotation type. * @return the annotation type @@ -342,8 +343,8 @@ > E[] getEnumArray(String attributeName, Class type) * @return the value as a {@link MergedAnnotation} * @throws NoSuchElementException if there is no matching attribute */ - MergedAnnotation getAnnotation(String attributeName, - Class type) throws NoSuchElementException; + MergedAnnotation getAnnotation(String attributeName, Class type) + throws NoSuchElementException; /** * Return a required annotation array attribute value from the annotation. @@ -413,10 +414,9 @@ MergedAnnotation[] getAnnotationArray(String attribute MergedAnnotation filterAttributes(Predicate predicate); /** - * Return a new view of the annotation that exposes non-merged attribute - * values. Methods from this view will return attribute values with only - * alias mirroring rules applied. Aliases to parent attributes will not be - * applied. + * Return a new view of the annotation that exposes non-merged attribute values. + * Methods from this view will return attribute values with only alias mirroring + * rules applied. Aliases to parent attributes will not be applied. * @return a non-merged view of the annotation */ MergedAnnotation withNonMergedAttributes(); @@ -431,9 +431,9 @@ MergedAnnotation[] getAnnotationArray(String attribute Map asMap(MapValues... options); /** - * Return a {@link Map} of the supplied type that contains all the - * annotation attributes. The {@link MapValues} options may be used to - * change the way that values are added. + * Return a {@link Map} of the supplied type that contains all the annotation + * attributes. The {@link MapValues} options may be used to change the way + * that values are added. * @param factory a map factory or {@code null} to return an immutable map. * @param options map value options * @return a map containing the attributes and values @@ -443,22 +443,19 @@ > T asMap( /** * Return a type-safe synthesized version of this annotation that can be - * used directly in code. The result is synthesized using a JDK - * {@link Proxy} and as a result may incur a computational cost when first - * invoked. - * @return a sythesized version of the annotation. + * used directly in code. The result is synthesized using a JDK {@link Proxy} + * and as a result may incur a computational cost when first invoked. + * @return a synthesized version of the annotation. * @throws NoSuchElementException on a missing annotation */ A synthesize() throws NoSuchElementException; /** * Optionally return type-safe synthesized version of this annotation based - * on a condition predicate. The result is synthesized using a JDK - * {@link Proxy} and as a result may incur a computational cost when first - * invoked. - * @param condition the test to determine if the annotation can be - * sythesized - * @return a optional containing the sythesized version of the annotation or + * on a condition predicate. The result is synthesized using a JDK {@link Proxy} + * and as a result may incur a computational cost when first invoked. + * @param condition the test to determine if the annotation can be synthesized + * @return a optional containing the synthesized version of the annotation or * an empty optional if the condition doesn't match * @throws NoSuchElementException on a missing annotation * @see MergedAnnotationPredicates @@ -466,6 +463,7 @@ > T asMap( Optional synthesize(@Nullable Predicate> condition) throws NoSuchElementException; + /** * Return an {@link MergedAnnotation} that represents a missing annotation * (i.e. one that is not present). @@ -494,8 +492,7 @@ static MergedAnnotation from(A annotation) { * @param annotation the annotation to include * @return a {@link MergedAnnotation} instance for the annotation */ - static MergedAnnotation from(@Nullable Object source, - A annotation) { + static MergedAnnotation from(@Nullable Object source, A annotation) { return TypeMappedAnnotation.from(source, annotation); } @@ -520,8 +517,9 @@ static MergedAnnotation from(Class annotationType) * attributes * @see #from(AnnotatedElement, Class, Map) */ - static MergedAnnotation from(Class annotationType, - @Nullable Map attributes) { + static MergedAnnotation from( + Class annotationType, @Nullable Map attributes) { + return from(null, annotationType, attributes); } @@ -538,8 +536,8 @@ static MergedAnnotation from(Class annotationType, * attributes */ static MergedAnnotation from( - @Nullable AnnotatedElement source, Class annotationType, - @Nullable Map attributes) { + @Nullable AnnotatedElement source, Class annotationType, @Nullable Map attributes) { + return TypeMappedAnnotation.from(source, annotationType, attributes); } @@ -561,7 +559,6 @@ enum MapValues { */ ANNOTATION_TO_MAP; - protected final boolean isIn(MapValues... options) { for (MapValues candidate : options) { if (candidate == this) { @@ -572,11 +569,9 @@ protected final boolean isIn(MapValues... options) { } /** - * Factory method to create a {@link MapValues} array from a set of - * boolean flags. + * Factory method to create a {@link MapValues} array from a set of boolean flags. * @param classToString if {@link MapValues#CLASS_TO_STRING} is included - * @param annotationsToMap if {@link MapValues#ANNOTATION_TO_MAP} is - * included + * @param annotationsToMap if {@link MapValues#ANNOTATION_TO_MAP} is included * @return a new {@link MapValues} array */ public static MapValues[] of(boolean classToString, boolean annotationsToMap) { @@ -591,7 +586,6 @@ private static void addIfTrue(Set result, T value, boolean test) { result.add(value); } } - } } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java index cf45a40442e5..51d0c09a4e73 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java @@ -27,7 +27,6 @@ import java.util.stream.Collector.Characteristics; import org.springframework.core.annotation.MergedAnnotation.MapValues; -import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -42,8 +41,7 @@ public abstract class MergedAnnotationCollectors { private static final Characteristics[] NO_CHARACTERISTICS = {}; - private static final Characteristics[] IDENTITY_FINISH_CHARACTERISTICS = { - Characteristics.IDENTITY_FINISH }; + private static final Characteristics[] IDENTITY_FINISH_CHARACTERISTICS = {Characteristics.IDENTITY_FINISH}; private MergedAnnotationCollectors() { @@ -128,15 +126,14 @@ private MergedAnnotationCollectors() { Function, MultiValueMap> finisher, MapValues... options) { - Assert.notNull(finisher, "Finisher must not be null"); - Characteristics[] characteristics = isSameInstance(finisher, Function.identity()) ? - IDENTITY_FINISH_CHARACTERISTICS : - NO_CHARACTERISTICS; + Characteristics[] characteristics = (isSameInstance(finisher, Function.identity()) ? + IDENTITY_FINISH_CHARACTERISTICS : NO_CHARACTERISTICS); return Collector.of(LinkedMultiValueMap::new, (map, annotation) -> annotation.asMap(options).forEach(map::add), MergedAnnotationCollectors::merge, finisher, characteristics); } + private static boolean isSameInstance(Object instance, Object candidate) { return instance == candidate; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationPredicates.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationPredicates.java index 6255729376d0..b341ba31195f 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationPredicates.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationPredicates.java @@ -49,10 +49,7 @@ private MergedAnnotationPredicates() { * @param typeNames the names that should be matched * @return a {@link Predicate} to test the annotation type */ - public static Predicate> typeIn( - String... typeNames) { - - Assert.notNull(typeNames, "TypeNames must not be null"); + public static Predicate> typeIn(String... typeNames) { return annotation -> ObjectUtils.containsElement(typeNames, annotation.getType()); } @@ -64,12 +61,8 @@ public static Predicate> ty * @param types the types that should be matched * @return a {@link Predicate} to test the annotation type */ - public static Predicate> typeIn( - Class... types) { - - Assert.notNull(types, "Types must not be null"); - return annotation -> Arrays.stream(types) - .anyMatch(type -> type.getName().equals(annotation.getType())); + public static Predicate> typeIn(Class... types) { + return annotation -> Arrays.stream(types).anyMatch(type -> type.getName().equals(annotation.getType())); } /** @@ -80,10 +73,7 @@ public static Predicate> ty * @param types the type names or classes that should be matched * @return a {@link Predicate} to test the annotation type */ - public static Predicate> typeIn( - Collection types) { - - Assert.notNull(types, "Types must not be null"); + public static Predicate> typeIn(Collection types) { return annotation -> types.stream() .map(type -> type instanceof Class ? ((Class) type).getName() : type.toString()) .anyMatch(typeName -> typeName.equals(annotation.getType())); @@ -103,7 +93,6 @@ public static Predicate> ty public static Predicate> firstRunOf( Function, ?> valueExtractor) { - Assert.notNull(valueExtractor, "ValueExtractor must not be null"); return new FirstRunOfPredicate<>(valueExtractor); } @@ -120,7 +109,6 @@ public static Predicate> firstRunOf( public static Predicate> unique( Function, K> keyExtractor) { - Assert.notNull(keyExtractor, "KeyExtractor must not be null"); return new UniquePredicate<>(keyExtractor); } @@ -129,8 +117,7 @@ public static Predicate> unique( * {@link Predicate} implementation used for * {@link MergedAnnotationPredicates#firstRunOf(Function)}. */ - private static class FirstRunOfPredicate - implements Predicate> { + private static class FirstRunOfPredicate implements Predicate> { private final Function, ?> valueExtractor; @@ -139,13 +126,11 @@ private static class FirstRunOfPredicate @Nullable private Object lastValue; - - FirstRunOfPredicate( - Function, ?> valueExtractor) { + FirstRunOfPredicate(Function, ?> valueExtractor) { + Assert.notNull(valueExtractor, "Value extractor must not be null"); this.valueExtractor = valueExtractor; } - @Override public boolean test(@Nullable MergedAnnotation annotation) { if (!this.hasLastValue) { @@ -164,19 +149,17 @@ public boolean test(@Nullable MergedAnnotation annotation) { * {@link Predicate} implementation used for * {@link MergedAnnotationPredicates#unique(Function)}. */ - private static class UniquePredicate - implements Predicate> { + private static class UniquePredicate implements Predicate> { private final Function, K> keyExtractor; private final Set seen = new HashSet<>(); - UniquePredicate(Function, K> keyExtractor) { + Assert.notNull(keyExtractor, "Key extractor must not be null"); this.keyExtractor = keyExtractor; } - @Override public boolean test(@Nullable MergedAnnotation annotation) { K key = this.keyExtractor.apply(annotation); diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelector.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelector.java index 0aa5c22a4c4f..f3c45c8a379c 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelector.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelector.java @@ -47,7 +47,6 @@ default boolean isBestCandidate(MergedAnnotation annotation) { * @return the most appropriate annotation from the {@code existing} or * {@code candidate} */ - MergedAnnotation select(MergedAnnotation existing, - MergedAnnotation candidate); + MergedAnnotation select(MergedAnnotation existing, MergedAnnotation candidate); } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelectors.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelectors.java index 8db4efaefdfd..b4fb270714f7 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelectors.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationSelectors.java @@ -70,8 +70,9 @@ public boolean isBestCandidate(MergedAnnotation annotation) { } @Override - public MergedAnnotation select(MergedAnnotation existing, - MergedAnnotation candidate) { + public MergedAnnotation select( + MergedAnnotation existing, MergedAnnotation candidate) { + if (candidate.getDepth() < existing.getDepth()) { return candidate; } @@ -93,8 +94,9 @@ public boolean isBestCandidate(MergedAnnotation annotation) { } @Override - public MergedAnnotation select(MergedAnnotation existing, - MergedAnnotation candidate) { + public MergedAnnotation select( + MergedAnnotation existing, MergedAnnotation candidate) { + if (existing.getDepth() > 0 && candidate.getDepth() == 0) { return candidate; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java index 8df5091287e6..302aeb201997 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java @@ -133,7 +133,7 @@ public interface MergedAnnotations extends Iterable * @param annotationType the annotation type to check * @return {@code true} if the annotation is present */ - boolean isPresent(@Nullable Class annotationType); + boolean isPresent(Class annotationType); /** * Return if the specified annotation is directly present. Equivalent to @@ -141,7 +141,7 @@ public interface MergedAnnotations extends Iterable * @param annotationType the annotation type to check * @return {@code true} if the annotation is present */ - boolean isPresent(@Nullable String annotationType); + boolean isPresent(String annotationType); /** * Return if the specified annotation is directly present. Equivalent to @@ -149,7 +149,7 @@ public interface MergedAnnotations extends Iterable * @param annotationType the annotation type to check * @return {@code true} if the annotation is present */ - boolean isDirectlyPresent(@Nullable Class annotationType); + boolean isDirectlyPresent(Class annotationType); /** * Return if the specified annotation is either directly present, or @@ -158,7 +158,7 @@ public interface MergedAnnotations extends Iterable * @param annotationType the annotation type to check * @return {@code true} if the annotation is present */ - boolean isDirectlyPresent(@Nullable String annotationType); + boolean isDirectlyPresent(String annotationType); /** * Return the {@link MergedAnnotationSelectors#nearest() nearest} matching @@ -167,7 +167,7 @@ public interface MergedAnnotations extends Iterable * @param annotationType the annotation type to get * @return a {@link MergedAnnotation} instance */ - MergedAnnotation get(@Nullable Class annotationType); + MergedAnnotation get(Class annotationType); /** * Return the {@link MergedAnnotationSelectors#nearest() nearest} matching @@ -179,7 +179,7 @@ public interface MergedAnnotations extends Iterable * @return a {@link MergedAnnotation} instance * @see MergedAnnotationPredicates */ - MergedAnnotation get(@Nullable Class annotationType, + MergedAnnotation get(Class annotationType, @Nullable Predicate> predicate); /** @@ -195,7 +195,7 @@ MergedAnnotation get(@Nullable Class annotationType * @see MergedAnnotationPredicates * @see MergedAnnotationSelectors */ - MergedAnnotation get(@Nullable Class annotationType, + MergedAnnotation get(Class annotationType, @Nullable Predicate> predicate, @Nullable MergedAnnotationSelector selector); @@ -206,7 +206,7 @@ MergedAnnotation get(@Nullable Class annotationType * @param annotationType the annotation type to get * @return a {@link MergedAnnotation} instance */ - MergedAnnotation get(@Nullable String annotationType); + MergedAnnotation get(String annotationType); /** * Return the {@link MergedAnnotationSelectors#nearest() nearest} matching @@ -218,7 +218,7 @@ MergedAnnotation get(@Nullable Class annotationType * @return a {@link MergedAnnotation} instance * @see MergedAnnotationPredicates */ - MergedAnnotation get(@Nullable String annotationType, + MergedAnnotation get(String annotationType, @Nullable Predicate> predicate); /** @@ -234,7 +234,7 @@ MergedAnnotation get(@Nullable String annotationType, * @see MergedAnnotationPredicates * @see MergedAnnotationSelectors */ - MergedAnnotation get(@Nullable String annotationType, + MergedAnnotation get(String annotationType, @Nullable Predicate> predicate, @Nullable MergedAnnotationSelector selector); @@ -245,8 +245,7 @@ MergedAnnotation get(@Nullable String annotationType, * @param annotationType the annotation type to match * @return a stream of matching annotations */ - Stream> stream( - @Nullable Class annotationType); + Stream> stream(Class annotationType); /** * Stream all annotations and meta-annotations that match the specified @@ -255,8 +254,7 @@ Stream> stream( * @param annotationType the annotation type to match * @return a stream of matching annotations */ - Stream> stream( - @Nullable String annotationType); + Stream> stream(String annotationType); /** * Stream all contained annotations and meta-annotations contained in this @@ -269,6 +267,7 @@ Stream> stream( */ Stream> stream(); + /** * Create a new {@link MergedAnnotations} instance containing all * annotations and meta-annotations from the specified element. The @@ -280,7 +279,7 @@ Stream> stream( * @return a {@link MergedAnnotations} instance containing the element * annotations */ - static MergedAnnotations from(@Nullable AnnotatedElement element) { + static MergedAnnotations from(AnnotatedElement element) { return from(element, SearchStrategy.DIRECT); } @@ -293,10 +292,8 @@ static MergedAnnotations from(@Nullable AnnotatedElement element) { * @return a {@link MergedAnnotations} instance containing the merged * element annotations */ - static MergedAnnotations from(@Nullable AnnotatedElement element, - SearchStrategy searchStrategy) { - return from(element, searchStrategy, RepeatableContainers.standardRepeatables(), - AnnotationFilter.PLAIN); + static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy) { + return from(element, searchStrategy, RepeatableContainers.standardRepeatables(), AnnotationFilter.PLAIN); } /** @@ -312,11 +309,10 @@ static MergedAnnotations from(@Nullable AnnotatedElement element, * @return a {@link MergedAnnotations} instance containing the merged * element annotations */ - static MergedAnnotations from(@Nullable AnnotatedElement element, - SearchStrategy searchStrategy, RepeatableContainers repeatableContainers, - AnnotationFilter annotationFilter) { - return TypeMappedAnnotations.from(element, searchStrategy, repeatableContainers, - annotationFilter); + static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy, + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { + + return TypeMappedAnnotations.from(element, searchStrategy, repeatableContainers, annotationFilter); } /** @@ -342,8 +338,7 @@ static MergedAnnotations from(Annotation... annotations) { * @see #from(AnnotatedElement) */ static MergedAnnotations from(@Nullable Object source, Annotation... annotations) { - return from(source, annotations, RepeatableContainers.standardRepeatables(), - AnnotationFilter.PLAIN); + return from(source, annotations, RepeatableContainers.standardRepeatables(), AnnotationFilter.PLAIN); } /** @@ -360,10 +355,9 @@ static MergedAnnotations from(@Nullable Object source, Annotation... annotations * @return a {@link MergedAnnotations} instance containing the annotations */ static MergedAnnotations from(@Nullable Object source, Annotation[] annotations, - RepeatableContainers repeatableContainers, - AnnotationFilter annotationFilter) { - return TypeMappedAnnotations.from(source, annotations, repeatableContainers, - annotationFilter); + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { + + return TypeMappedAnnotations.from(source, annotations, repeatableContainers, annotationFilter); } @@ -406,7 +400,6 @@ enum SearchStrategy { * not need to be meta-annotated with {@link Inherited @Inherited}. */ EXHAUSTIVE - } } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MissingMergedAnnotation.java b/spring-core/src/main/java/org/springframework/core/annotation/MissingMergedAnnotation.java index 09188b723cf5..255f4434b3b3 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MissingMergedAnnotation.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MissingMergedAnnotation.java @@ -34,8 +34,7 @@ * @since 5.2 * @param the annotation type */ -final class MissingMergedAnnotation - extends AbstractMergedAnnotation { +final class MissingMergedAnnotation extends AbstractMergedAnnotation { private static final MissingMergedAnnotation INSTANCE = new MissingMergedAnnotation<>(); @@ -153,6 +152,7 @@ protected A createSynthesized() { throw new NoSuchElementException("Unable to synthesize missing annotation"); } + @SuppressWarnings("unchecked") static MergedAnnotation getInstance() { return (MergedAnnotation) INSTANCE; diff --git a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java index 5064fd386413..000f513d59d7 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java @@ -92,8 +92,8 @@ public static Integer getOrder(Class type) { * @param annotations the annotation to consider * @return the order value, or {@code null} if none can be found */ - static Integer getOrderFromAnnotations(AnnotatedElement element, - MergedAnnotations annotations) { + @Nullable + static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) { if (!(element instanceof Class)) { return findOrder(annotations); } @@ -106,6 +106,7 @@ static Integer getOrderFromAnnotations(AnnotatedElement element, return result; } + @Nullable private static Integer findOrder(MergedAnnotations annotations) { MergedAnnotation orderAnnotation = annotations.get(Order.class); if (orderAnnotation.isPresent()) { diff --git a/spring-core/src/main/java/org/springframework/core/annotation/PackagesAnnotationFilter.java b/spring-core/src/main/java/org/springframework/core/annotation/PackagesAnnotationFilter.java index 05f57daf49e9..3b161a6daa9c 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/PackagesAnnotationFilter.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/PackagesAnnotationFilter.java @@ -29,7 +29,7 @@ * @author Phillip Webb * @since 5.2 */ -class PackagesAnnotationFilter implements AnnotationFilter { +final class PackagesAnnotationFilter implements AnnotationFilter { private final String[] prefixes; @@ -40,8 +40,9 @@ class PackagesAnnotationFilter implements AnnotationFilter { Assert.notNull(packages, "Packages must not be null"); this.prefixes = new String[packages.length]; for (int i = 0; i < packages.length; i++) { - Assert.hasText(packages[i], "Package must not have empty elements"); - this.prefixes[i] = packages[i] + "."; + String pkg = packages[i]; + Assert.hasText(pkg, "Package must not have empty elements"); + this.prefixes[i] = pkg + "."; } Arrays.sort(this.prefixes); this.hashCode = Arrays.hashCode(this.prefixes); @@ -49,27 +50,25 @@ class PackagesAnnotationFilter implements AnnotationFilter { @Override - public boolean matches(@Nullable String annotationType) { - if (annotationType != null) { - for (String prefix : this.prefixes) { - if (annotationType.startsWith(prefix)) { - return true; - } + public boolean matches(String annotationType) { + for (String prefix : this.prefixes) { + if (annotationType.startsWith(prefix)) { + return true; } } return false; } + @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) { + public boolean equals(@Nullable Object other) { + if (this == other) { return true; } - if (obj == null || getClass() != obj.getClass()) { + if (other == null || getClass() != other.getClass()) { return false; } - PackagesAnnotationFilter other = (PackagesAnnotationFilter) obj; - return Arrays.equals(this.prefixes, other.prefixes); + return Arrays.equals(this.prefixes, ((PackagesAnnotationFilter) other).prefixes); } @Override diff --git a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java index ce4732a62f17..fc609478fc10 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java @@ -73,16 +73,16 @@ Annotation[] findRepeatedAnnotations(Annotation annotation) { return this.parent.findRepeatedAnnotations(annotation); } + @Override - public boolean equals(@Nullable Object obj) { - if (obj == this) { + public boolean equals(@Nullable Object other) { + if (other == this) { return true; } - if (obj == null || getClass() != obj.getClass()) { + if (other == null || getClass() != other.getClass()) { return false; } - RepeatableContainers other = (RepeatableContainers) obj; - return Objects.equals(this.parent, other.parent); + return Objects.equals(this.parent, ((RepeatableContainers) other).parent); } @Override @@ -90,6 +90,7 @@ public int hashCode() { return ObjectUtils.nullSafeHashCode(this.parent); } + /** * Return a {@link RepeatableContainers} instance that searches using Java's * {@link Repeatable @Repeatable} annotation. @@ -198,10 +199,8 @@ private static class ExplicitRepeatableContainer extends RepeatableContainers { private final Method valueMethod; - ExplicitRepeatableContainer(@Nullable RepeatableContainers parent, - Class repeatable, - @Nullable Class container) { + Class repeatable, @Nullable Class container) { super(parent); Assert.notNull(repeatable, "Repeatable must not be null"); @@ -235,11 +234,9 @@ private static class ExplicitRepeatableContainer extends RepeatableContainers { this.valueMethod = valueMethod; } - private Class deduceContainer( - Class repeatable) { - + private Class deduceContainer(Class repeatable) { Repeatable annotation = repeatable.getAnnotation(Repeatable.class); - Assert.notNull(annotation, "Annotation type must be a repeatable annotation: " + + Assert.notNull(annotation, () -> "Annotation type must be a repeatable annotation: " + "failed to resolve container type for " + repeatable.getName()); return annotation.value(); } @@ -254,13 +251,12 @@ Annotation[] findRepeatedAnnotations(Annotation annotation) { } @Override - public boolean equals(@Nullable Object obj) { - if (super.equals(obj)) { - ExplicitRepeatableContainer other = (ExplicitRepeatableContainer) obj; - return this.container.equals(other.container) && - this.repeatable.equals(other.repeatable); + public boolean equals(@Nullable Object other) { + if (!super.equals(other)) { + return false; } - return false; + ExplicitRepeatableContainer otherErc = (ExplicitRepeatableContainer) other; + return (this.container.equals(otherErc.container) && this.repeatable.equals(otherErc.repeatable)); } @Override @@ -270,7 +266,6 @@ public int hashCode() { hashCode = 31 * hashCode + this.repeatable.hashCode(); return hashCode; } - } @@ -284,7 +279,6 @@ private static class NoRepeatableContainers extends RepeatableContainers { NoRepeatableContainers() { super(null); } - } } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java index f21b0b32a348..fb6448b5464f 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java @@ -33,8 +33,8 @@ /** * {@link InvocationHandler} for an {@link Annotation} that Spring has - * synthesized (i.e., wrapped in a dynamic proxy) with additional - * functionality. + * synthesized (i.e. wrapped in a dynamic proxy) with additional + * functionality such as attribute alias handling. * * @author Sam Brannen * @author Phillip Webb @@ -44,8 +44,7 @@ * @see AnnotationAttributeExtractor * @see AnnotationUtils#synthesizeAnnotation(Annotation, AnnotatedElement) */ -class SynthesizedMergedAnnotationInvocationHandler - implements InvocationHandler { +final class SynthesizedMergedAnnotationInvocationHandler implements InvocationHandler { private final MergedAnnotation annotation; @@ -57,10 +56,8 @@ class SynthesizedMergedAnnotationInvocationHandler private volatile Integer hashCode; - private SynthesizedMergedAnnotationInvocationHandler(MergedAnnotation annotation, - Class type) { - - Assert.notNull(annotation, "Annotation must not be null"); + private SynthesizedMergedAnnotationInvocationHandler(MergedAnnotation annotation, Class type) { + Assert.notNull(annotation, "MergedAnnotation must not be null"); Assert.notNull(type, "Type must not be null"); Assert.isTrue(type.isAnnotation(), "Type must be an annotation"); this.annotation = annotation; @@ -90,18 +87,15 @@ public Object invoke(Object proxy, Method method, Object[] args) { return getAttributeValue(method); } throw new AnnotationConfigurationException(String.format( - "Method [%s] is unsupported for synthesized annotation type [%s]", method, - this.type)); + "Method [%s] is unsupported for synthesized annotation type [%s]", method, this.type)); } private boolean isAnnotationTypeMethod(Method method) { - return Objects.equals(method.getName(), "annotationType") - && method.getParameterCount() == 0; + return (Objects.equals(method.getName(), "annotationType") && method.getParameterCount() == 0); } /** - * See {@link Annotation#equals(Object)} for a definition of the required - * algorithm. + * See {@link Annotation#equals(Object)} for a definition of the required algorithm. * @param other the other object to compare against */ private boolean annotationEquals(Object other) { @@ -123,8 +117,7 @@ private boolean annotationEquals(Object other) { } /** - * See {@link Annotation#hashCode()} for a definition of the required - * algorithm. + * See {@link Annotation#hashCode()} for a definition of the required algorithm. */ private int annotationHashCode() { Integer hashCode = this.hashCode; @@ -182,26 +175,22 @@ private Object getAttributeValue(Method method) { String name = method.getName(); Class type = ClassUtils.resolvePrimitiveIfNecessary(method.getReturnType()); return this.annotation.getValue(name, type).orElseThrow( - () -> new NoSuchElementException("No value found for attribute named '" - + name + "' in merged annotation " + this.annotation.getType())); + () -> new NoSuchElementException("No value found for attribute named '" + name + + "' in merged annotation " + this.annotation.getType())); } @SuppressWarnings("unchecked") - static A createProxy(MergedAnnotation annotation, - Class type) { + static A createProxy(MergedAnnotation annotation, Class type) { ClassLoader classLoader = type.getClassLoader(); - InvocationHandler handler = new SynthesizedMergedAnnotationInvocationHandler<>( - annotation, type); - Class[] interfaces = isVisible(classLoader, SynthesizedAnnotation.class) - ? new Class[] { type, SynthesizedAnnotation.class } - : new Class[] { type }; + InvocationHandler handler = new SynthesizedMergedAnnotationInvocationHandler<>(annotation, type); + Class[] interfaces = isVisible(classLoader, SynthesizedAnnotation.class) ? + new Class[] {type, SynthesizedAnnotation.class} : new Class[] {type}; return (A) Proxy.newProxyInstance(classLoader, interfaces, handler); } private static boolean isVisible(ClassLoader classLoader, Class interfaceClass) { try { - return Class.forName(interfaceClass.getName(), false, - classLoader) == interfaceClass; + return Class.forName(interfaceClass.getName(), false, classLoader) == interfaceClass; } catch (ClassNotFoundException ex) { return false; diff --git a/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java b/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java index 3eaef51cb72f..c20e89b61c88 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java @@ -190,13 +190,12 @@ public boolean hasDefaultValue(String attributeName) { @Override @SuppressWarnings("unchecked") - public MergedAnnotation getAnnotation(String attributeName, - Class type) throws NoSuchElementException { + public MergedAnnotation getAnnotation(String attributeName, Class type) + throws NoSuchElementException { - Assert.notNull(attributeName, "AttributeName must not be null"); - Assert.notNull(type, "Type must not be null"); int attributeIndex = getAttributeIndex(attributeName, true); Method attribute = this.mapping.getAttributes().get(attributeIndex); + Assert.notNull(type, "Type must not be null"); Assert.isAssignable(type, attribute.getReturnType(), "Attribute " + attributeName + " type mismatch:"); return (MergedAnnotation) getRequiredValue(attributeIndex, Object.class); @@ -207,13 +206,12 @@ public MergedAnnotation getAnnotation(String attribute public MergedAnnotation[] getAnnotationArray( String attributeName, Class type) throws NoSuchElementException { - Assert.notNull(attributeName, "AttributeName must not be null"); - Assert.notNull(type, "Type must not be null"); int attributeIndex = getAttributeIndex(attributeName, true); Method attribute = this.mapping.getAttributes().get(attributeIndex); Class componentType = attribute.getReturnType().getComponentType(); + Assert.notNull(type, "Type must not be null"); Assert.notNull(componentType, () -> "Attribute " + attributeName + " is not an array"); - Assert.isAssignable(type, componentType, "Attribute " + attributeName + " component type mismatch:"); + Assert.isAssignable(type, componentType, () -> "Attribute " + attributeName + " component type mismatch:"); return (MergedAnnotation[]) getRequiredValue(attributeIndex, Object.class); } @@ -229,7 +227,6 @@ public Optional getDefaultValue(String attributeName, Class type) { @Override public MergedAnnotation filterAttributes(Predicate predicate) { - Assert.notNull(predicate, "Predicate must not be null"); if (this.attributeFilter != null) { predicate = this.attributeFilter.and(predicate); } @@ -250,9 +247,8 @@ public MergedAnnotation withNonMergedAttributes() { public > T asMap( @Nullable Function, T> factory, MapValues... options) { - T map = factory != null ? factory.apply(this) : (T) new LinkedHashMap(); - Assert.state(map != null, - "Factory used to create MergedAnnotation Map must not return null;"); + T map = (factory != null ? factory.apply(this) : (T) new LinkedHashMap()); + Assert.state(map != null, "Factory used to create MergedAnnotation Map must not return null"); AttributeMethods attributes = this.mapping.getAttributes(); for (int i = 0; i < attributes.size(); i++) { Method attribute = attributes.get(i); @@ -361,14 +357,13 @@ private Object toString(@Nullable Object value) { @Nullable protected T getAttributeValue(String attributeName, Class type) { int attributeIndex = getAttributeIndex(attributeName, false); - return attributeIndex != -1 ? getValue(attributeIndex, type) : null; + return (attributeIndex != -1 ? getValue(attributeIndex, type) : null); } protected final T getRequiredValue(int attributeIndex, Class type) { T value = getValue(attributeIndex, type); if (value == null) { - throw new NoSuchElementException( - "No element at attribute index " + attributeIndex); + throw new NoSuchElementException("No element at attribute index " + attributeIndex); } return value; } @@ -457,8 +452,7 @@ else if (value instanceof MergedAnnotation && type.isAnnotation()) { MergedAnnotation annotation = (MergedAnnotation) value; value = annotation.synthesize(); } - else if (value instanceof MergedAnnotation[] && type.isArray() - && type.getComponentType().isAnnotation()) { + else if (value instanceof MergedAnnotation[] && type.isArray() && type.getComponentType().isAnnotation()) { MergedAnnotation[] annotations = (MergedAnnotation[]) value; Object array = Array.newInstance(type.getComponentType(), annotations.length); for (int i = 0; i < annotations.length; i++) { @@ -484,8 +478,7 @@ private Object adaptForAttribute(Method attribute, Object value) { if (attributeType.isAnnotation()) { return adaptToMergedAnnotation(value,(Class) attributeType); } - if (attributeType.isArray() && - attributeType.getComponentType().isAnnotation() && + if (attributeType.isArray() && attributeType.getComponentType().isAnnotation() && value.getClass().isArray()) { MergedAnnotation[] result = new MergedAnnotation[Array.getLength(value)]; for (int i = 0; i < result.length; i++) { @@ -539,10 +532,9 @@ private Class getDefaultAdaptType(Method attribute) { } private int getAttributeIndex(String attributeName, boolean required) { - Assert.hasText(attributeName, "AttributeName must not be null"); - int attributeIndex = isFiltered(attributeName) ? - -1 : - this.mapping.getAttributes().indexOf(attributeName); + Assert.hasText(attributeName, "Attribute name must not be null"); + int attributeIndex = (isFiltered(attributeName) ? -1 : + this.mapping.getAttributes().indexOf(attributeName)); if (attributeIndex == -1 && required) { throw new NoSuchElementException("No attribute named '" + attributeName + "' present in merged annotation " + getType()); @@ -562,20 +554,16 @@ private Class getAnnotationType() { return (Class) this.mapping.getAnnotationType(); } - static MergedAnnotation from(@Nullable Object source, - A annotation) { - + static MergedAnnotation from(@Nullable Object source, A annotation) { Assert.notNull(annotation, "Annotation must not be null"); - AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - annotation.annotationType()); - return new TypeMappedAnnotation<>(mappings.get(0), source, annotation, - ReflectionUtils::invokeMethod, 0); + AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(annotation.annotationType()); + return new TypeMappedAnnotation<>(mappings.get(0), source, annotation, ReflectionUtils::invokeMethod, 0); } static MergedAnnotation from(@Nullable Object source, Class annotationType, @Nullable Map attributes) { - Assert.notNull(annotationType, "AnnotationType must not be null"); + Assert.notNull(annotationType, "Annotation type must not be null"); AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(annotationType); return new TypeMappedAnnotation<>(mappings.get(0), source, attributes, TypeMappedAnnotation::extractFromMap, 0); @@ -596,9 +584,8 @@ static TypeMappedAnnotation createIfPossible( } if (logger.isEnabled()) { String type = mapping.getAnnotationType().getName(); - String item = mapping.getDepth() == 0 ? - "annotation " + type : - "meta-annotation " + type + " from " + mapping.getRoot().getAnnotationType().getName(); + String item = (mapping.getDepth() == 0 ? "annotation " + type : + "meta-annotation " + type + " from " + mapping.getRoot().getAnnotationType().getName()); logger.log("Failed to introspect " + item, source, ex); } return null; @@ -608,7 +595,7 @@ static TypeMappedAnnotation createIfPossible( @SuppressWarnings("unchecked") @Nullable private static Object extractFromMap(Method attribute, @Nullable Object map) { - return map != null ? ((Map) map).get(attribute.getName()) : null; + return (map != null ? ((Map) map).get(attribute.getName()) : null); } } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotations.java b/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotations.java index 4225edf0a6c4..7b2cddbfca7d 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotations.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotations.java @@ -36,14 +36,14 @@ * annotations and meta-annotations using {@link AnnotationTypeMappings}. * * @author Phillip Webb - * @since 5.1 + * @since 5.2 */ final class TypeMappedAnnotations implements MergedAnnotations { private static final AnnotationFilter FILTER_ALL = annotationType -> true; - private static final MergedAnnotations NONE = new TypeMappedAnnotations(null, - new Annotation[0], RepeatableContainers.none(), FILTER_ALL); + private static final MergedAnnotations NONE = new TypeMappedAnnotations( + null, new Annotation[0], RepeatableContainers.none(), FILTER_ALL); @Nullable @@ -67,8 +67,7 @@ final class TypeMappedAnnotations implements MergedAnnotations { private TypeMappedAnnotations(AnnotatedElement element, SearchStrategy searchStrategy, - RepeatableContainers repeatableContainers, - AnnotationFilter annotationFilter) { + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { this.source = element; this.element = element; @@ -79,8 +78,7 @@ private TypeMappedAnnotations(AnnotatedElement element, SearchStrategy searchStr } private TypeMappedAnnotations(@Nullable Object source, Annotation[] annotations, - RepeatableContainers repeatableContainers, - AnnotationFilter annotationFilter) { + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { this.source = source; this.element = null; @@ -92,8 +90,8 @@ private TypeMappedAnnotations(@Nullable Object source, Annotation[] annotations, @Override - public boolean isPresent(@Nullable Class annotationType) { - if (annotationType == null || this.annotationFilter.matches(annotationType)) { + public boolean isPresent(Class annotationType) { + if (this.annotationFilter.matches(annotationType)) { return false; } return Boolean.TRUE.equals(scan(annotationType, @@ -101,8 +99,8 @@ public boolean isPresent(@Nullable Class annotationTyp } @Override - public boolean isPresent(@Nullable String annotationType) { - if (annotationType == null || this.annotationFilter.matches(annotationType)) { + public boolean isPresent(String annotationType) { + if (this.annotationFilter.matches(annotationType)) { return false; } return Boolean.TRUE.equals(scan(annotationType, @@ -119,8 +117,8 @@ public boolean isDirectlyPresent(@Nullable Class annot } @Override - public boolean isDirectlyPresent(@Nullable String annotationType) { - if (annotationType == null || this.annotationFilter.matches(annotationType)) { + public boolean isDirectlyPresent(String annotationType) { + if (this.annotationFilter.matches(annotationType)) { return false; } return Boolean.TRUE.equals(scan(annotationType, @@ -128,57 +126,53 @@ public boolean isDirectlyPresent(@Nullable String annotationType) { } @Override - public MergedAnnotation get( - @Nullable Class annotationType) { - + public MergedAnnotation get(Class annotationType) { return get(annotationType, null, null); } @Override - public MergedAnnotation get( - @Nullable Class annotationType, + public MergedAnnotation get(Class annotationType, @Nullable Predicate> predicate) { return get(annotationType, predicate, null); } @Override - public MergedAnnotation get( - @Nullable Class annotationType, + public MergedAnnotation get(Class annotationType, @Nullable Predicate> predicate, @Nullable MergedAnnotationSelector selector) { - if (annotationType == null || this.annotationFilter.matches(annotationType)) { + if (this.annotationFilter.matches(annotationType)) { return MergedAnnotation.missing(); } MergedAnnotation result = scan(annotationType, new MergedAnnotationFinder<>(annotationType, predicate, selector)); - return result != null ? result : MergedAnnotation.missing(); + return (result != null ? result : MergedAnnotation.missing()); } @Override - public MergedAnnotation get( - @Nullable String annotationType) { + public MergedAnnotation get(String annotationType) { return get(annotationType, null, null); } @Override - public MergedAnnotation get(@Nullable String annotationType, + public MergedAnnotation get(String annotationType, @Nullable Predicate> predicate) { + return get(annotationType, predicate, null); } @Override - public MergedAnnotation get(@Nullable String annotationType, + public MergedAnnotation get(String annotationType, @Nullable Predicate> predicate, @Nullable MergedAnnotationSelector selector) { - if (annotationType == null || this.annotationFilter.matches(annotationType)) { + if (this.annotationFilter.matches(annotationType)) { return MergedAnnotation.missing(); } MergedAnnotation result = scan(annotationType, new MergedAnnotationFinder<>(annotationType, predicate, selector)); - return result != null ? result : MergedAnnotation.missing(); + return (result != null ? result : MergedAnnotation.missing()); } @Override @@ -261,13 +255,11 @@ static MergedAnnotations from(@Nullable AnnotatedElement element, if (element == null || AnnotationsScanner.isKnownEmpty(element, searchStrategy, annotationFilter)) { return NONE; } - return new TypeMappedAnnotations(element, searchStrategy, repeatableContainers, - annotationFilter); + return new TypeMappedAnnotations(element, searchStrategy, repeatableContainers, annotationFilter); } - static MergedAnnotations from(@Nullable Object source, - Annotation[] annotations, RepeatableContainers repeatableContainers, - AnnotationFilter annotationFilter) { + static MergedAnnotations from(@Nullable Object source, Annotation[] annotations, + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { if (annotations.length == 0) { return NONE; @@ -282,8 +274,8 @@ private static boolean isMappingForType(@Nullable AnnotationTypeMapping mapping, return false; } Class actualType = mapping.getAnnotationType(); - return !annotationFilter.matches(actualType) && - (requiredType == null || actualType == requiredType || actualType.getName().equals(requiredType)); + return (!annotationFilter.matches(actualType) && + (requiredType == null || actualType == requiredType || actualType.getName().equals(requiredType))); } @@ -291,8 +283,7 @@ private static boolean isMappingForType(@Nullable AnnotationTypeMapping mapping, * {@link AnnotationsProcessor} used to detect if an annotation is directly * or meta-present. */ - private static final class IsPresent - implements AnnotationsProcessor { + private static final class IsPresent implements AnnotationsProcessor { /** * Shared instances that save us needing to create a new processor for @@ -307,14 +298,12 @@ private static final class IsPresent SHARED[3] = new IsPresent(RepeatableContainers.standardRepeatables(), AnnotationFilter.PLAIN, false); } - private final RepeatableContainers repeatableContainers; private final AnnotationFilter annotationFilter; private final boolean directOnly; - private IsPresent(RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter, boolean directOnly) { @@ -323,7 +312,6 @@ private IsPresent(RepeatableContainers repeatableContainers, this.directOnly = directOnly; } - @Override @Nullable public Boolean doWithAnnotations(Object requiredType, int aggregateIndex, @@ -374,7 +362,6 @@ static IsPresent get(RepeatableContainers repeatableContainers, } return new IsPresent(repeatableContainers, annotationFilter, directOnly); } - } @@ -395,18 +382,14 @@ private class MergedAnnotationFinder @Nullable private MergedAnnotation result; - - MergedAnnotationFinder(Object requiredType, - @Nullable Predicate> predicate, + MergedAnnotationFinder(Object requiredType, @Nullable Predicate> predicate, @Nullable MergedAnnotationSelector selector) { this.requiredType = requiredType; this.predicate = predicate; - this.selector = selector != null ? selector - : MergedAnnotationSelectors.nearest(); + this.selector = (selector != null ? selector : MergedAnnotationSelectors.nearest()); } - @Override @Nullable public MergedAnnotation doWithAggregate(Object context, int aggregateIndex) { @@ -431,26 +414,21 @@ public MergedAnnotation doWithAnnotations(Object type, int aggregateIndex, } @Nullable - private MergedAnnotation process(Object type, int aggregateIndex, - @Nullable Object source, Annotation annotation) { - Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations( - annotation); + private MergedAnnotation process( + Object type, int aggregateIndex, @Nullable Object source, Annotation annotation) { + + Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(annotation); if (repeatedAnnotations != null) { - return doWithAnnotations(type, aggregateIndex, source, - repeatedAnnotations); + return doWithAnnotations(type, aggregateIndex, source, repeatedAnnotations); } AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - annotation.annotationType(), - annotationFilter); + annotation.annotationType(), annotationFilter); for (int i = 0; i < mappings.size(); i++) { AnnotationTypeMapping mapping = mappings.get(i); - if (isMappingForType(mapping, annotationFilter, - this.requiredType)) { + if (isMappingForType(mapping, annotationFilter, this.requiredType)) { MergedAnnotation candidate = TypeMappedAnnotation.createIfPossible( - mapping, source, annotation, aggregateIndex, - IntrospectionFailureLogger.INFO); - if (candidate != null && (this.predicate == null - || this.predicate.test(candidate))) { + mapping, source, annotation, aggregateIndex, IntrospectionFailureLogger.INFO); + if (candidate != null && (this.predicate == null || this.predicate.test(candidate))) { if (this.selector.isBestCandidate(candidate)) { return candidate; } @@ -463,24 +441,21 @@ private MergedAnnotation process(Object type, int aggregateIndex, private void updateLastResult(MergedAnnotation candidate) { MergedAnnotation lastResult = this.result; - this.result = lastResult != null - ? this.selector.select(lastResult, candidate) - : candidate; + this.result = (lastResult != null ? this.selector.select(lastResult, candidate) : candidate); } @Override @Nullable public MergedAnnotation finish(@Nullable MergedAnnotation result) { - return result != null ? result : this.result; + return (result != null ? result : this.result); } - } + /** * {@link AnnotationsProcessor} that collects {@link Aggregate} instances. */ - private class AggregatesCollector - implements AnnotationsProcessor> { + private class AggregatesCollector implements AnnotationsProcessor> { private final List aggregates = new ArrayList<>(); @@ -488,12 +463,12 @@ private class AggregatesCollector @Nullable public List doWithAnnotations(Object criteria, int aggregateIndex, @Nullable Object source, Annotation[] annotations) { + this.aggregates.add(createAggregate(aggregateIndex, source, annotations)); return null; } - private Aggregate createAggregate(int aggregateIndex, @Nullable Object source, - Annotation[] annotations) { + private Aggregate createAggregate(int aggregateIndex, @Nullable Object source, Annotation[] annotations) { List aggregateAnnotations = getAggregateAnnotations(annotations); return new Aggregate(aggregateIndex, source, aggregateAnnotations); } @@ -504,17 +479,12 @@ private List getAggregateAnnotations(Annotation[] annotations) { return result; } - private void addAggregateAnnotations(List aggregateAnnotations, - Annotation[] annotations) { + private void addAggregateAnnotations(List aggregateAnnotations, Annotation[] annotations) { for (Annotation annotation : annotations) { - if (annotation != null - && !annotationFilter.matches( - annotation)) { - Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations( - annotation); + if (annotation != null && !annotationFilter.matches(annotation)) { + Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(annotation); if (repeatedAnnotations != null) { - addAggregateAnnotations(aggregateAnnotations, - repeatedAnnotations); + addAggregateAnnotations(aggregateAnnotations, repeatedAnnotations); } else { aggregateAnnotations.add(annotation); @@ -527,9 +497,9 @@ private void addAggregateAnnotations(List aggregateAnnotations, public List finish(@Nullable List processResult) { return this.aggregates; } - } + private static class Aggregate { private final int aggregateIndex; @@ -541,8 +511,7 @@ private static class Aggregate { private final AnnotationTypeMappings[] mappings; - Aggregate(int aggregateIndex, @Nullable Object source, - List annotations) { + Aggregate(int aggregateIndex, @Nullable Object source, List annotations) { this.aggregateIndex = aggregateIndex; this.source = source; this.annotations = annotations; @@ -575,15 +544,14 @@ MergedAnnotation createMergedAnnotationIfPossible( this.mappings[annotationIndex].get(mappingIndex), this.source, this.annotations.get(annotationIndex), this.aggregateIndex, logger); } - } + /** * {@link Spliterator} used to consume merged annotations from the * aggregates in depth fist order. */ - private class AggregatesSpliterator - implements Spliterator> { + private class AggregatesSpliterator implements Spliterator> { @Nullable private final Object requiredType; @@ -595,8 +563,7 @@ private class AggregatesSpliterator @Nullable private int[] mappingCursors; - AggregatesSpliterator(@Nullable Object requiredType, - List aggregates) { + AggregatesSpliterator(@Nullable Object requiredType, List aggregates) { this.requiredType = requiredType; this.aggregates = aggregates; this.aggregateCursor = 0; @@ -614,8 +581,7 @@ public boolean tryAdvance(Consumer> action) { return false; } - private boolean tryAdvance(Aggregate aggregate, - Consumer> action) { + private boolean tryAdvance(Aggregate aggregate, Consumer> action) { if (this.mappingCursors == null) { this.mappingCursors = new int[aggregate.size()]; } @@ -646,8 +612,7 @@ private boolean tryAdvance(Aggregate aggregate, } @Nullable - private AnnotationTypeMapping getNextSuitableMapping(Aggregate aggregate, - int annotationIndex) { + private AnnotationTypeMapping getNextSuitableMapping(Aggregate aggregate, int annotationIndex) { int[] cursors = this.mappingCursors; if (cursors != null) { AnnotationTypeMapping mapping; @@ -691,7 +656,6 @@ public long estimateSize() { public int characteristics() { return NONNULL | IMMUTABLE; } - } } diff --git a/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java b/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java index 6a18ae7d9079..3769295c6868 100644 --- a/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java +++ b/spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java @@ -35,8 +35,6 @@ import java.util.concurrent.locks.ReentrantLock; import org.springframework.lang.Nullable; -import org.springframework.util.ConcurrentReferenceHashMap.Reference; -import org.springframework.util.ConcurrentReferenceHashMap.Restructure; /** * A {@link ConcurrentHashMap} that uses {@link ReferenceType#SOFT soft} or @@ -579,7 +577,7 @@ protected final void restructureIfNecessary(boolean allowResize) { } } - private void restructure(boolean allowResize, Reference ref) { + private void restructure(boolean allowResize, @Nullable Reference ref) { boolean needsResize; lock(); try { diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java index f26a07bf0bd4..57f61f48e52d 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java @@ -700,17 +700,12 @@ private void assertWebMapping(AnnotatedElement element) throws ArrayComparisonFa assertArrayEquals("path attribute: ", asArray("/test"), webMapping.path()); } - @Test - public void javaLangAnnotationTypeViaFindMergedAnnotation() throws Exception { - Constructor deprecatedCtor = Date.class.getConstructor(String.class); - assertEquals(deprecatedCtor.getAnnotation(Deprecated.class), findMergedAnnotation(deprecatedCtor, Deprecated.class)); - assertEquals(Date.class.getAnnotation(Deprecated.class), findMergedAnnotation(Date.class, Deprecated.class)); - } - @Test public void javaxAnnotationTypeViaFindMergedAnnotation() throws Exception { - assertEquals(ResourceHolder.class.getAnnotation(Resource.class), findMergedAnnotation(ResourceHolder.class, Resource.class)); - assertEquals(SpringAppConfigClass.class.getAnnotation(Resource.class), findMergedAnnotation(SpringAppConfigClass.class, Resource.class)); + assertEquals(ResourceHolder.class.getAnnotation(Resource.class), + findMergedAnnotation(ResourceHolder.class, Resource.class)); + assertEquals(SpringAppConfigClass.class.getAnnotation(Resource.class), + findMergedAnnotation(SpringAppConfigClass.class, Resource.class)); } @Test diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationFilterTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationFilterTests.java index 1e4553e98abd..83a3a424de40 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationFilterTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationFilterTests.java @@ -16,19 +16,16 @@ package org.springframework.core.annotation; -import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; -import java.util.Collection; import org.junit.Test; import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.*; /** * Tests for {@link AnnotationFilter}. @@ -37,35 +34,22 @@ */ public class AnnotationFilterTests { - private static final AnnotationFilter FILTER = annotationType -> ObjectUtils.nullSafeEquals( - annotationType, TestAnnotation.class.getName()); + private static final AnnotationFilter FILTER = annotationType -> + ObjectUtils.nullSafeEquals(annotationType, TestAnnotation.class.getName()); - @Test - public void matchesAnnotationWhenAnnotationIsNullReturnsFalse() { - TestAnnotation annotation = null; - assertThat(FILTER.matches(annotation)).isFalse(); - } @Test public void matchesAnnotationWhenMatchReturnsTrue() { - TestAnnotation annotation = WithTestAnnotation.class.getDeclaredAnnotation( - TestAnnotation.class); + TestAnnotation annotation = WithTestAnnotation.class.getDeclaredAnnotation(TestAnnotation.class); assertThat(FILTER.matches(annotation)).isTrue(); } @Test public void matchesAnnotationWhenNoMatchReturnsFalse() { - OtherAnnotation annotation = WithOtherAnnotation.class.getDeclaredAnnotation( - OtherAnnotation.class); + OtherAnnotation annotation = WithOtherAnnotation.class.getDeclaredAnnotation(OtherAnnotation.class); assertThat(FILTER.matches(annotation)).isFalse(); } - @Test - public void matchesAnnotationClassWhenAnnotationClassIsNullReturnsFalse() { - Class annotationType = null; - assertThat(FILTER.matches(annotationType)).isFalse(); - } - @Test public void matchesAnnotationClassWhenMatchReturnsTrue() { Class annotationType = TestAnnotation.class; @@ -109,27 +93,15 @@ public void javaWhenOtherAnnotationReturnsFalse() { } @Test - public void noneWhenNonNullReturnsFalse() { + public void noneReturnsFalse() { assertThat(AnnotationFilter.NONE.matches(Retention.class)).isFalse(); assertThat(AnnotationFilter.NONE.matches(Nullable.class)).isFalse(); assertThat(AnnotationFilter.NONE.matches(TestAnnotation.class)).isFalse(); - assertThat(AnnotationFilter.NONE.matches((Annotation) null)).isFalse(); - assertThat(AnnotationFilter.NONE.matches((Class) null)).isFalse(); - assertThat(AnnotationFilter.NONE.matches((String) null)).isFalse(); } @Test public void pacakgesReturnsPackagesAnnotationFilter() { - assertThat(AnnotationFilter.packages("com.example")).isInstanceOf( - PackagesAnnotationFilter.class); - } - - @Test - public void mostAppropriateForCollectionWhenAnnotationTypesIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy( - () -> AnnotationFilter.mostAppropriateFor( - (Collection>) null)).withMessage( - "AnnotationTypes must not be null"); + assertThat(AnnotationFilter.packages("com.example")).isInstanceOf(PackagesAnnotationFilter.class); } @Test @@ -146,14 +118,6 @@ public void mostAppropriateForCollectionWhenCantUsePlainReturnsNone() { assertThat(filter).isSameAs(AnnotationFilter.NONE); } - @Test - public void mostAppropriateForArrayWhenAnnotationTypesIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy( - () -> AnnotationFilter.mostAppropriateFor( - (Class[]) null)).withMessage( - "AnnotationTypes must not be null"); - } - @Test public void mostAppropriateForArrayReturnsPlainWhenPossible() { AnnotationFilter filter = AnnotationFilter.mostAppropriateFor( @@ -168,24 +132,21 @@ public void mostAppropriateForArrayWhenCantUsePlainReturnsNone() { assertThat(filter).isSameAs(AnnotationFilter.NONE); } - @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotation { + @Retention(RetentionPolicy.RUNTIME) + @interface TestAnnotation { } @TestAnnotation static class WithTestAnnotation { - } @Retention(RetentionPolicy.RUNTIME) - static @interface OtherAnnotation { - + @interface OtherAnnotation { } @OtherAnnotation static class WithOtherAnnotation { - } } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationTypeMappingsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationTypeMappingsTests.java index 1f16c1a1282e..040ec9948e06 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationTypeMappingsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationTypeMappingsTests.java @@ -28,7 +28,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; - import javax.annotation.Nullable; import org.junit.Test; @@ -47,35 +46,24 @@ */ public class AnnotationTypeMappingsTests { - @Test - public void forAnnotationTypeWhenAnnotationIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy( - () -> AnnotationTypeMappings.forAnnotationType(null)).withMessage( - "AnnotationType must not be null"); - } - @Test public void forAnnotationTypeWhenNoMetaAnnotationsReturnsMappings() { - AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - SimpleAnnotation.class); + AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(SimpleAnnotation.class); assertThat(mappings.size()).isEqualTo(1); assertThat(mappings.get(0).getAnnotationType()).isEqualTo(SimpleAnnotation.class); assertThat(getAll(mappings)).flatExtracting( - AnnotationTypeMapping::getAnnotationType).containsExactly( - SimpleAnnotation.class); + AnnotationTypeMapping::getAnnotationType).containsExactly(SimpleAnnotation.class); } @Test public void forAnnotationWhenHasSpringAnnotationReturnsFilteredMappings() { - AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - WithSpringLangAnnotation.class); + AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(WithSpringLangAnnotation.class); assertThat(mappings.size()).isEqualTo(1); } @Test public void forAnnotationTypeWhenMetaAnnotationsReturnsMappings() { - AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - MetaAnnotated.class); + AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(MetaAnnotated.class); assertThat(mappings.size()).isEqualTo(6); assertThat(getAll(mappings)).flatExtracting( AnnotationTypeMapping::getAnnotationType).containsExactly( @@ -85,33 +73,27 @@ public void forAnnotationTypeWhenMetaAnnotationsReturnsMappings() { @Test public void forAnnotationTypeWhenHasRepeatingMetaAnnotationReturnsMapping() { - AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - WithRepeatedMetaAnnotations.class); + AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(WithRepeatedMetaAnnotations.class); assertThat(mappings.size()).isEqualTo(3); assertThat(getAll(mappings)).flatExtracting( AnnotationTypeMapping::getAnnotationType).containsExactly( - WithRepeatedMetaAnnotations.class, Repeating.class, - Repeating.class); + WithRepeatedMetaAnnotations.class, Repeating.class, Repeating.class); } @Test public void forAnnotationTypeWhenSelfAnnotatedReturnsMapping() { - AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - SelfAnnotated.class); + AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(SelfAnnotated.class); assertThat(mappings.size()).isEqualTo(1); assertThat(getAll(mappings)).flatExtracting( - AnnotationTypeMapping::getAnnotationType).containsExactly( - SelfAnnotated.class); + AnnotationTypeMapping::getAnnotationType).containsExactly(SelfAnnotated.class); } @Test public void forAnnotationTypeWhenFormsLoopReturnsMapping() { - AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType( - LoopA.class); + AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(LoopA.class); assertThat(mappings.size()).isEqualTo(2); assertThat(getAll(mappings)).flatExtracting( - AnnotationTypeMapping::getAnnotationType).containsExactly(LoopA.class, - LoopB.class); + AnnotationTypeMapping::getAnnotationType).containsExactly(LoopA.class, LoopB.class); } @Test diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java index 4d7a284bc278..6dcd6e4bc2c3 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java @@ -540,13 +540,6 @@ public void getDefaultValueFromAnnotationType() { assertEquals(Ordered.LOWEST_PRECEDENCE, getDefaultValue(Order.class)); } - @Test - public void findRepeatableAnnotationOnComposedAnnotation() { - Repeatable repeatable = findAnnotation(MyRepeatableMeta1.class, Repeatable.class); - assertNotNull(repeatable); - assertEquals(MyRepeatableContainer.class, repeatable.value()); - } - @Test public void getRepeatableAnnotationsDeclaredOnMethod() throws Exception { Method method = InterfaceWithRepeated.class.getMethod("foo"); diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java index 7579dcdc140e..c27077691d9f 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java @@ -511,6 +511,7 @@ public String finish(String result) { assertThat(result).isEqualTo("OK"); } + private Method methodFrom(Class type) { return ReflectionUtils.findMethod(type, "method"); } @@ -532,81 +533,68 @@ private Stream scan(AnnotatedElement element, SearchStrategy searchStrat return result.stream(); } - @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotation1 { + @Retention(RetentionPolicy.RUNTIME) + @interface TestAnnotation1 { } @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotation2 { - + @interface TestAnnotation2 { } @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotation3 { - + @interface TestAnnotation3 { } @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotation4 { - + @interface TestAnnotation4 { } @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotation5 { - + @interface TestAnnotation5 { } @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotation6 { - + @interface TestAnnotation6 { } @Retention(RetentionPolicy.RUNTIME) @Inherited - static @interface TestInheritedAnnotation1 { - + @interface TestInheritedAnnotation1 { } @Retention(RetentionPolicy.RUNTIME) @Inherited - static @interface TestInheritedAnnotation2 { - + @interface TestInheritedAnnotation2 { } @Retention(RetentionPolicy.RUNTIME) @Inherited - static @interface TestInheritedAnnotation3 { - + @interface TestInheritedAnnotation3 { } @Retention(RetentionPolicy.RUNTIME) @Inherited - static @interface TestInheritedAnnotation4 { - + @interface TestInheritedAnnotation4 { } @Retention(RetentionPolicy.RUNTIME) @Inherited - static @interface TestInheritedAnnotation5 { - + @interface TestInheritedAnnotation5 { } @Retention(RetentionPolicy.RUNTIME) - static @interface OnSuperClass { - + @interface OnSuperClass { } @Retention(RetentionPolicy.RUNTIME) - static @interface OnInterface { - + @interface OnInterface { } static class WithNoAnnotations { public void method() { } - } @TestAnnotation1 @@ -615,7 +603,6 @@ static class WithSingleAnnotation { @TestAnnotation1 public void method() { } - } @TestAnnotation1 @@ -626,7 +613,6 @@ static class WithMultipleAnnotations { @TestAnnotation2 public void method() { } - } @TestAnnotation2 @@ -637,7 +623,6 @@ static class SingleSuperclass { @TestInheritedAnnotation2 public void method() { } - } @TestAnnotation1 @@ -646,7 +631,6 @@ static class WithSingleSuperclass extends SingleSuperclass { @TestAnnotation1 public void method() { } - } @TestInheritedAnnotation2 @@ -655,7 +639,6 @@ static class WithSingleSuperclassAndDoubleInherited extends SingleSuperclass { @TestAnnotation1 public void method() { } - } @TestAnnotation1 @@ -664,17 +647,15 @@ static class WithSingleInterface implements SingleInterface { @TestAnnotation1 public void method() { } - } @TestAnnotation2 @TestInheritedAnnotation2 - static interface SingleInterface { + interface SingleInterface { @TestAnnotation2 @TestInheritedAnnotation2 - public void method(); - + void method(); } @TestAnnotation1 @@ -683,7 +664,6 @@ static class WithHierarchy extends HierarchySuperclass implements HierarchyInter @TestAnnotation1 public void method() { } - } @TestAnnotation2 @@ -694,7 +674,6 @@ static class HierarchySuperclass extends HierarchySuperSuperclass { @TestInheritedAnnotation2 public void method() { } - } @TestAnnotation3 @@ -703,33 +682,29 @@ static class HierarchySuperSuperclass implements HierarchySuperSuperclassInterfa @TestAnnotation3 public void method() { } - } @TestAnnotation4 - static interface HierarchySuperSuperclassInterface { + interface HierarchySuperSuperclassInterface { @TestAnnotation4 - public void method(); - + void method(); } @TestAnnotation5 @TestInheritedAnnotation5 - static interface HierarchyInterface extends HierarchyInterfaceInterface { + interface HierarchyInterface extends HierarchyInterfaceInterface { @TestAnnotation5 @TestInheritedAnnotation5 - public void method(); - + void method(); } @TestAnnotation6 - static interface HierarchyInterfaceInterface { + interface HierarchyInterfaceInterface { @TestAnnotation6 - public void method(); - + void method(); } static class BridgedMethod implements BridgeMethod { @@ -738,37 +713,32 @@ static class BridgedMethod implements BridgeMethod { @TestAnnotation1 public void method(String arg) { } - } - static interface BridgeMethod { + interface BridgeMethod { @TestAnnotation2 void method(T arg); - } - static class Ignoreable implements IgnoreableOverrideInterface1, - IgnoreableOverrideInterface2, Serializable { + @SuppressWarnings("serial") + static class Ignoreable implements IgnoreableOverrideInterface1, IgnoreableOverrideInterface2, Serializable { @TestAnnotation1 public void method() { } - } - static interface IgnoreableOverrideInterface1 { + interface IgnoreableOverrideInterface1 { @Nullable - public void method(); - + void method(); } - static interface IgnoreableOverrideInterface2 { + interface IgnoreableOverrideInterface2 { @Nullable - public void method(); - + void method(); } static abstract class MultipleMethods implements MultipleMethodsInterface { @@ -776,7 +746,6 @@ static abstract class MultipleMethods implements MultipleMethodsInterface { @TestAnnotation1 public void method() { } - } interface MultipleMethodsInterface { @@ -786,23 +755,19 @@ interface MultipleMethodsInterface { @TestAnnotation2 void method1(); - } static class GenericOverride implements GenericOverrideInterface { @TestAnnotation1 public void method(String argument) { - } - } - static interface GenericOverrideInterface { + interface GenericOverrideInterface { @TestAnnotation2 void method(T argument); - } static abstract class GenericNonOverride @@ -810,16 +775,13 @@ static abstract class GenericNonOverride @TestAnnotation1 public void method(StringBuilder argument) { - } - } - static interface GenericNonOverrideInterface { + interface GenericNonOverrideInterface { @TestAnnotation2 void method(T argument); - } } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationCollectorsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationCollectorsTests.java index 8ecf4b1f7aad..223be195ffc3 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationCollectorsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationCollectorsTests.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; -import java.util.function.Function; import java.util.stream.Stream; import org.junit.Test; @@ -31,8 +30,7 @@ import org.springframework.core.annotation.MergedAnnotation.MapValues; import org.springframework.util.MultiValueMap; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.*; /** * Tests for {@link MergedAnnotationCollectors}. @@ -93,19 +91,11 @@ public void toFinishedMultiValueMapCollectsMultiValueMap() { assertThat(map.get("finished")).containsExactly(true); } - @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void toFinishedMultiValueMapWhenFinisherIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy(() -> stream().collect( - MergedAnnotationCollectors.toMultiValueMap((Function) null))).withMessage( - "Finisher must not be null"); - } - private Stream> stream() { - return MergedAnnotations.from(WithTestAnnotations.class).stream( - TestAnnotation.class); + return MergedAnnotations.from(WithTestAnnotations.class).stream(TestAnnotation.class); } + @Retention(RetentionPolicy.RUNTIME) @Repeatable(TestAnnotations.class) @interface TestAnnotation { @@ -124,14 +114,12 @@ private Stream> stream() { @interface TestAnnotations { TestAnnotation[] value(); - } @TestAnnotation("a") @TestAnnotation(name = "b", extra = String.class) @TestAnnotation(name = "c", extra = Integer.class) static class WithTestAnnotations { - } } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationPredicatesTests.java b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationPredicatesTests.java index 4dbefa836b8e..f5394a0eab3b 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationPredicatesTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationPredicatesTests.java @@ -16,20 +16,17 @@ package org.springframework.core.annotation; -import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import org.junit.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.assertj.core.api.Assertions.*; /** * Tests for {@link MergedAnnotationPredicates}. @@ -54,35 +51,18 @@ public void typeInStringArrayWhenNameDoesNotMatchRejects() { MissingAnnotation.class.getName())).rejects(annotation); } - @Test - public void typeInStringArrayWhenStringArraysIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy( - () -> MergedAnnotationPredicates.typeIn((String[]) null)).withMessage( - "TypeNames must not be null"); - } - @Test public void typeInClassArrayWhenNameMatchesAccepts() { - MergedAnnotation annotation = MergedAnnotations.from( - WithTestAnnotation.class).get(TestAnnotation.class); - assertThat(MergedAnnotationPredicates.typeIn(TestAnnotation.class)).accepts( - annotation); + MergedAnnotation annotation = + MergedAnnotations.from(WithTestAnnotation.class).get(TestAnnotation.class); + assertThat(MergedAnnotationPredicates.typeIn(TestAnnotation.class)).accepts(annotation); } @Test public void typeInClassArrayWhenNameDoesNotMatchRejects() { - MergedAnnotation annotation = MergedAnnotations.from( - WithTestAnnotation.class).get(TestAnnotation.class); - assertThat(MergedAnnotationPredicates.typeIn(MissingAnnotation.class)).rejects( - annotation); - } - - @Test - public void typeInClassArrayWhenClassArraysIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy( - () -> MergedAnnotationPredicates.typeIn( - (Class[]) null)).withMessage( - "Types must not be null"); + MergedAnnotation annotation = + MergedAnnotations.from(WithTestAnnotation.class).get(TestAnnotation.class); + assertThat(MergedAnnotationPredicates.typeIn(MissingAnnotation.class)).rejects(annotation); } @Test @@ -90,8 +70,7 @@ public void typeInCollectionWhenMatchesStringInCollectionAccepts() { MergedAnnotation annotation = MergedAnnotations.from( WithTestAnnotation.class).get(TestAnnotation.class); assertThat(MergedAnnotationPredicates.typeIn( - Collections.singleton(TestAnnotation.class.getName()))).accepts( - annotation); + Collections.singleton(TestAnnotation.class.getName()))).accepts(annotation); } @Test @@ -107,15 +86,7 @@ public void typeInCollectionWhenDoesNotMatchAnyRejects() { MergedAnnotation annotation = MergedAnnotations.from( WithTestAnnotation.class).get(TestAnnotation.class); assertThat(MergedAnnotationPredicates.typeIn(Arrays.asList( - MissingAnnotation.class.getName(), MissingAnnotation.class))).rejects( - annotation); - } - - @Test - public void typeInCollectionWhenCollectionIsNullThrowsException() { - assertThatIllegalArgumentException().isThrownBy( - () -> MergedAnnotationPredicates.typeIn( - (Collection) null)).withMessage("Types must not be null"); + MissingAnnotation.class.getName(), MissingAnnotation.class))).rejects(annotation); } @Test @@ -125,15 +96,13 @@ public void firstRunOfAcceptsOnlyFirstRun() { MergedAnnotationPredicates.firstRunOf( this::firstCharOfValue)).collect(Collectors.toList()); assertThat(filtered.stream().map( - annotation -> annotation.getString("value"))).containsExactly("a1", "a2", - "a3"); + annotation -> annotation.getString("value"))).containsExactly("a1", "a2", "a3"); } @Test public void firstRunOfWhenValueExtractorIsNullThrowsException() { assertThatIllegalArgumentException().isThrownBy( - () -> MergedAnnotationPredicates.firstRunOf(null)).withMessage( - "ValueExtractor must not be null"); + () -> MergedAnnotationPredicates.firstRunOf(null)); } @Test @@ -143,42 +112,38 @@ public void uniqueAcceptsUniquely() { MergedAnnotationPredicates.unique( this::firstCharOfValue)).collect(Collectors.toList()); assertThat(filtered.stream().map( - annotation -> annotation.getString("value"))).containsExactly("a1", "b1", - "c1"); + annotation -> annotation.getString("value"))).containsExactly("a1", "b1", "c1"); } @Test public void uniqueWhenKeyExtractorIsNullThrowsException() { assertThatIllegalArgumentException().isThrownBy( - () -> MergedAnnotationPredicates.unique(null)).withMessage( - "KeyExtractor must not be null"); + () -> MergedAnnotationPredicates.unique(null)); } private char firstCharOfValue(MergedAnnotation annotation) { return annotation.getString("value").charAt(0); } + @Retention(RetentionPolicy.RUNTIME) @Repeatable(TestAnnotations.class) - static @interface TestAnnotation { + @interface TestAnnotation { String value() default ""; } @Retention(RetentionPolicy.RUNTIME) - static @interface TestAnnotations { + @interface TestAnnotations { TestAnnotation[] value(); - } - static @interface MissingAnnotation { - + @interface MissingAnnotation { } @TestAnnotation("test") static class WithTestAnnotation { - } @TestAnnotation("a1") @@ -191,7 +156,6 @@ static class WithTestAnnotation { @TestAnnotation("c2") @TestAnnotation("c3") static class WithMultipleTestAnnotation { - } } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java index 4c14ba0785a0..033df3f5a599 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java @@ -24,19 +24,16 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.stream.Collectors; import java.util.stream.Stream; - import javax.annotation.Resource; import org.junit.Test; @@ -74,44 +71,41 @@ public class MergedAnnotationsTests { @Test public void streamWhenFromNonAnnotatedClass() { - assertThat(MergedAnnotations.from(NonAnnotatedClass.class).stream( - TransactionalComponent.class)).isEmpty(); + assertThat(MergedAnnotations.from(NonAnnotatedClass.class). + stream(TransactionalComponent.class)).isEmpty(); } @Test public void streamWhenFromClassWithMetaDepth1() { - Stream names = MergedAnnotations.from( - TransactionalComponent.class).stream().map(MergedAnnotation::getType); + Stream names = MergedAnnotations.from(TransactionalComponent.class) + .stream().map(MergedAnnotation::getType); assertThat(names).containsExactly(Transactional.class.getName(), Component.class.getName(), Indexed.class.getName()); } @Test public void streamWhenFromClassWithMetaDepth2() { - Stream names = MergedAnnotations.from( - ComposedTransactionalComponent.class).stream().map( - MergedAnnotation::getType); + Stream names = MergedAnnotations.from(ComposedTransactionalComponent.class) + .stream().map(MergedAnnotation::getType); assertThat(names).containsExactly(TransactionalComponent.class.getName(), - Transactional.class.getName(), Component.class.getName(), - Indexed.class.getName()); + Transactional.class.getName(), Component.class.getName(), Indexed.class.getName()); } @Test public void isPresentWhenFromNonAnnotatedClass() { - assertThat(MergedAnnotations.from(NonAnnotatedClass.class).isPresent( - Transactional.class)).isFalse(); + assertThat(MergedAnnotations.from(NonAnnotatedClass.class). + isPresent(Transactional.class)).isFalse(); } @Test public void isPresentWhenFromAnnotationClassWithMetaDepth0() { - assertThat(MergedAnnotations.from(TransactionalComponent.class).isPresent( - TransactionalComponent.class)).isFalse(); + assertThat(MergedAnnotations.from(TransactionalComponent.class). + isPresent(TransactionalComponent.class)).isFalse(); } @Test public void isPresentWhenFromAnnotationClassWithMetaDepth1() { - MergedAnnotations annotations = MergedAnnotations.from( - TransactionalComponent.class); + MergedAnnotations annotations = MergedAnnotations.from(TransactionalComponent.class); assertThat(annotations.isPresent(Transactional.class)).isTrue(); assertThat(annotations.isPresent(Component.class)).isTrue(); } @@ -204,8 +198,6 @@ public void collectMultiValueMapFavorsInheritedComposedAnnotationsOverMoreLocall * type within the class hierarchy. Such undesirable behavior would cause * the logic in * {@link org.springframework.context.annotation.ProfileCondition} to fail. - * - * @see org.springframework.core.env.EnvironmentSystemIntegrationTests#mostSpecificDerivedClassDrivesEnvironment_withDevEnvAndDerivedDevConfigClass */ @Test public void collectMultiValueMapFromClassWithLocalAnnotationThatShadowsAnnotationFromSuperclass() { @@ -218,8 +210,6 @@ public void collectMultiValueMapFromClassWithLocalAnnotationThatShadowsAnnotatio /** * Note: this functionality is required by * {@link org.springframework.context.annotation.ProfileCondition}. - * - * @see org.springframework.core.env.EnvironmentSystemIntegrationTests */ @Test public void collectMultiValueMapFromClassWithMultipleComposedAnnotations() { @@ -629,38 +619,26 @@ public void getWithExhaustiveWithLocalAliasesThatConflictWithAttributesInMetaAnn } @Test - public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaConvention() - throws Exception { + public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaConvention() throws Exception { testGetWithExhaustiveWebMapping( WebController.class.getMethod("postMappedWithPathAttribute")); } @Test - public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaAliasFor() - throws Exception { + public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaAliasFor() throws Exception { testGetWithExhaustiveWebMapping( WebController.class.getMethod("getMappedWithValueAttribute")); testGetWithExhaustiveWebMapping( WebController.class.getMethod("getMappedWithPathAttribute")); } - private void testGetWithExhaustiveWebMapping(AnnotatedElement element) - throws ArrayComparisonFailure { + private void testGetWithExhaustiveWebMapping(AnnotatedElement element) throws ArrayComparisonFailure { MergedAnnotation annotation = MergedAnnotations.from(element, SearchStrategy.EXHAUSTIVE).get(RequestMapping.class); assertThat(annotation.getStringArray("value")).containsExactly("/test"); assertThat(annotation.getStringArray("path")).containsExactly("/test"); } - @Test - public void getDirectWithJavaLangAnnotationType() throws Exception { - Constructor deprecatedConstructor = Date.class.getConstructor(String.class); - MergedAnnotation annotation = MergedAnnotations.from(deprecatedConstructor, - SearchStrategy.DIRECT, RepeatableContainers.standardRepeatables(), - AnnotationFilter.NONE).get(Deprecated.class); - assertThat(annotation.isPresent()).isTrue(); - } - @Test public void getDirectWithJavaxAnnotationType() throws Exception { assertThat(MergedAnnotations.from(ResourceHolder.class).get( @@ -1267,14 +1245,6 @@ public void getDefaultValueFromAnnotationType() { Ordered.LOWEST_PRECEDENCE); } - @Test - public void getRepeatableOnComposedAnnotation() { - MergedAnnotation annotation = MergedAnnotations.from(MyRepeatableMeta1.class, - SearchStrategy.EXHAUSTIVE, RepeatableContainers.none(), - AnnotationFilter.NONE).get(Repeatable.class); - assertThat(annotation.getClass("value")).isEqualTo(MyRepeatableContainer.class); - } - @Test public void getRepeatableDeclaredOnMethod() throws Exception { Method method = InterfaceWithRepeated.class.getMethod("foo"); @@ -1286,8 +1256,7 @@ public void getRepeatableDeclaredOnMethod() throws Exception { } @Test - public void getRepeatableDeclaredOnClassWithMissingAttributeAliasDeclaration() - throws Exception { + public void getRepeatableDeclaredOnClassWithMissingAttributeAliasDeclaration() { RepeatableContainers containers = RepeatableContainers.of( BrokenContextConfiguration.class, BrokenHierarchy.class); assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(