diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index f624074a289..331597a680a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -668,12 +668,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto @Nullable public A findAnnotationOnBean(String beanName, Class annotationType) throws NoSuchBeanDefinitionException { - return findMergedAnnotationOnBean(beanName, annotationType).synthesize( - MergedAnnotation::isPresent).orElse(null); + + return findMergedAnnotationOnBean(beanName, annotationType) + .synthesize(MergedAnnotation::isPresent).orElse(null); } private MergedAnnotation findMergedAnnotationOnBean( String beanName, Class annotationType) { + Class beanType = getType(beanName); if (beanType != null) { MergedAnnotation annotation = MergedAnnotations.from(beanType, 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 0c2e6796819..ee118b285e9 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 @@ -76,27 +76,19 @@ final class AnnotationTypeMapping { private final Set claimedAliases = new HashSet<>(); - AnnotationTypeMapping(Class annotationType) { - this(null, annotationType, null); - } - - AnnotationTypeMapping(AnnotationTypeMapping parent, Annotation annotation) { - this(parent, annotation.annotationType(), annotation); - } - AnnotationTypeMapping(@Nullable AnnotationTypeMapping parent, Class annotationType, @Nullable Annotation annotation) { this.parent = parent; - this.root = parent != null ? parent.getRoot() : this; - this.depth = parent == null ? 0 : parent.getDepth() + 1; + this.root = (parent != null ? parent.getRoot() : this); + this.depth = (parent == null ? 0 : parent.getDepth() + 1); this.annotationType = annotationType; this.annotation = annotation; this.attributes = AttributeMethods.forAnnotationType(annotationType); this.mirrorSets = new MirrorSets(); - this.aliasMappings = filledIntArray(this.attributes.size(), -1); - this.conventionMappings = filledIntArray(this.attributes.size(), -1); - this.annotationValueMappings = filledIntArray(this.attributes.size(), -1); + this.aliasMappings = filledIntArray(this.attributes.size()); + this.conventionMappings = filledIntArray(this.attributes.size()); + this.annotationValueMappings = filledIntArray(this.attributes.size()); this.annotationValueSource = new AnnotationTypeMapping[this.attributes.size()]; this.aliasedBy = resolveAliasedForTargets(); processAliases(); @@ -109,12 +101,10 @@ final class AnnotationTypeMapping { Map> aliasedBy = new HashMap<>(); for (int i = 0; i < this.attributes.size(); i++) { Method attribute = this.attributes.get(i); - AliasFor aliasFor = AnnotationsScanner.getDeclaredAnnotation(attribute, - AliasFor.class); + AliasFor aliasFor = AnnotationsScanner.getDeclaredAnnotation(attribute, AliasFor.class); if (aliasFor != null) { Method target = resolveAliasTarget(attribute, aliasFor); - aliasedBy.computeIfAbsent(target, key -> new ArrayList<>()).add( - attribute); + aliasedBy.computeIfAbsent(target, key -> new ArrayList<>()).add(attribute); } } return Collections.unmodifiableMap(aliasedBy); @@ -125,12 +115,10 @@ final class AnnotationTypeMapping { } private Method resolveAliasTarget(Method attribute, AliasFor aliasFor, boolean checkAliasPair) { - if (StringUtils.hasText(aliasFor.value()) && - StringUtils.hasText(aliasFor.attribute())) { + if (StringUtils.hasText(aliasFor.value()) && StringUtils.hasText(aliasFor.attribute())) { throw new AnnotationConfigurationException(String.format( - "In @AliasFor declared on %s, attribute 'attribute' and its alias " - + "'value' are present with values of '%s' and '%s', but " - + "only one is permitted.", + "In @AliasFor declared on %s, attribute 'attribute' and its alias 'value' " + + "are present with values of '%s' and '%s', but only one is permitted.", AttributeMethods.describe(attribute), aliasFor.attribute(), aliasFor.value())); } @@ -145,13 +133,11 @@ final class AnnotationTypeMapping { if (!StringUtils.hasLength(targetAttributeName)) { targetAttributeName = attribute.getName(); } - Method target = AttributeMethods.forAnnotationType(targetAnnotation) - .get(targetAttributeName); + Method target = AttributeMethods.forAnnotationType(targetAnnotation).get(targetAttributeName); if (target == null) { if (targetAnnotation == this.annotationType) { throw new AnnotationConfigurationException(String.format( - "@AliasFor declaration on %s declares an " - + "alias for '%s' which is not present.", + "@AliasFor declaration on %s declares an alias for '%s' which is not present.", AttributeMethods.describe(attribute), targetAttributeName)); } throw new AnnotationConfigurationException(String.format( @@ -161,9 +147,8 @@ final class AnnotationTypeMapping { } if (target == attribute) { throw new AnnotationConfigurationException(String.format( - "@AliasFor declaration on %s points to itself. " - + "Specify 'annotation' to point to a same-named " - + "attribute on a meta-annotation.", + "@AliasFor declaration on %s points to itself. " + + "Specify 'annotation' to point to a same-named attribute on a meta-annotation.", AttributeMethods.describe(attribute))); } if (!isCompatibleReturnType(attribute.getReturnType(), target.getReturnType())) { @@ -175,10 +160,10 @@ final class AnnotationTypeMapping { if (isAliasPair(target) && checkAliasPair) { AliasFor targetAliasFor = target.getAnnotation(AliasFor.class); if (targetAliasFor == null) { - throw new AnnotationConfigurationException( - String.format("%s must be declared as an @AliasFor '%s'.", - StringUtils.capitalize(AttributeMethods.describe(target)), - attribute.getName())); + throw new AnnotationConfigurationException(String.format( + "%s must be declared as an @AliasFor '%s'.", + StringUtils.capitalize(AttributeMethods.describe(target)), + attribute.getName())); } Method mirror = resolveAliasTarget(target, targetAliasFor, false); if (mirror != attribute) { @@ -288,10 +273,10 @@ final class AnnotationTypeMapping { for (int i = 0; i < this.attributes.size(); i++) { Method attribute = this.attributes.get(i); AnnotationTypeMapping mapping = this; - while (mapping.depth > 0) { + while (mapping != null && mapping.depth > 0) { int mapped = mapping.getAttributes().indexOf(attribute.getName()); - if (mapped != -1 && (this.annotationValueMappings[i] == -1 - || this.annotationValueSource[i].depth > mapping.depth)) { + if (mapped != -1 && (this.annotationValueMappings[i] == -1 || + this.annotationValueSource[i].depth > mapping.depth)) { this.annotationValueMappings[i] = mapped; this.annotationValueSource[i] = mapping; } @@ -320,8 +305,7 @@ final class AnnotationTypeMapping { Method target = resolveAliasTarget(attribute, aliasFor); throw new AnnotationConfigurationException(String.format( "@AliasFor declaration on %s declares an alias for %s which is not meta-present.", - AttributeMethods.describe(attribute), - AttributeMethods.describe(target))); + AttributeMethods.describe(attribute), AttributeMethods.describe(target))); } } } @@ -335,14 +319,12 @@ final class AnnotationTypeMapping { if (firstDefaultValue == null || mirrorDefaultValue == null) { throw new AnnotationConfigurationException(String.format( "Misconfigured aliases: %s and %s must declare default values.", - AttributeMethods.describe(firstAttribute), - AttributeMethods.describe(mirrorAttribute))); + AttributeMethods.describe(firstAttribute), AttributeMethods.describe(mirrorAttribute))); } if (!ObjectUtils.nullSafeEquals(firstDefaultValue, mirrorDefaultValue)) { throw new AnnotationConfigurationException(String.format( "Misconfigured aliases: %s and %s must declare the same default value.", - AttributeMethods.describe(firstAttribute), - AttributeMethods.describe(mirrorAttribute))); + AttributeMethods.describe(firstAttribute), AttributeMethods.describe(mirrorAttribute))); } } } @@ -438,8 +420,7 @@ final class AnnotationTypeMapping { return null; } AnnotationTypeMapping source = this.annotationValueSource[attributeIndex]; - return ReflectionUtils.invokeMethod(source.attributes.get(mapped), - source.annotation); + return ReflectionUtils.invokeMethod(source.attributes.get(mapped), source.annotation); } /** @@ -453,6 +434,7 @@ final class AnnotationTypeMapping { */ boolean isEquivalentToDefaultValue(int attributeIndex, Object value, BiFunction valueExtractor) { + Method attribute = this.attributes.get(attributeIndex); return isEquivalentToDefaultValue(attribute, value, valueExtractor); } @@ -465,20 +447,22 @@ final class AnnotationTypeMapping { return this.mirrorSets; } - private static int[] filledIntArray(int size, int value) { + + private static int[] filledIntArray(int size) { int[] array = new int[size]; - Arrays.fill(array, value); + Arrays.fill(array, -1); return array; } private static boolean isEquivalentToDefaultValue(Method attribute, Object value, BiFunction valueExtractor) { + return areEquivalent(attribute.getDefaultValue(), value, valueExtractor); } - private static boolean areEquivalent(@Nullable Object value, - @Nullable Object extractedValue, + private static boolean areEquivalent(@Nullable Object value, @Nullable Object extractedValue, BiFunction valueExtractor) { + if (ObjectUtils.nullSafeEquals(value, extractedValue)) { return true; } @@ -512,8 +496,8 @@ final class AnnotationTypeMapping { private static boolean areEquivalent(Annotation value, @Nullable Object extractedValue, BiFunction valueExtractor) { - AttributeMethods attributes = AttributeMethods.forAnnotationType( - value.annotationType()); + + AttributeMethods attributes = AttributeMethods.forAnnotationType(value.annotationType()); for (int i = 0; i < attributes.size(); i++) { Method attribute = attributes.get(i); if (!areEquivalent(ReflectionUtils.invokeMethod(attribute, value), @@ -535,13 +519,11 @@ final class AnnotationTypeMapping { private final MirrorSet[] assigned; - MirrorSets() { this.assigned = new MirrorSet[attributes.size()]; this.mirrorSets = new MirrorSet[0]; } - void updateFrom(Collection aliases) { MirrorSet mirrorSet = null; int size = 0; @@ -562,8 +544,7 @@ final class AnnotationTypeMapping { } if (mirrorSet != null) { mirrorSet.update(); - LinkedHashSet unique = new LinkedHashSet<>( - Arrays.asList(this.assigned)); + Set unique = new LinkedHashSet<>(Arrays.asList(this.assigned)); unique.remove(null); this.mirrorSets = unique.toArray(new MirrorSet[0]); } @@ -609,7 +590,6 @@ final class AnnotationTypeMapping { private final int[] indexes = new int[attributes.size()]; - void update() { this.size = 0; Arrays.fill(this.indexes, -1); @@ -629,8 +609,8 @@ final class AnnotationTypeMapping { for (int i = 0; i < this.size; i++) { Method attribute = attributes.get(this.indexes[i]); Object value = valueExtractor.apply(attribute, annotation); - boolean isDefaultValue = value == null || isEquivalentToDefaultValue( - attribute, value, valueExtractor); + boolean isDefaultValue = (value == null || + isEquivalentToDefaultValue(attribute, value, valueExtractor)); if (isDefaultValue || ObjectUtils.nullSafeEquals(lastValue, value)) { continue; } @@ -638,8 +618,8 @@ final class AnnotationTypeMapping { !ObjectUtils.nullSafeEquals(lastValue, value)) { String on = (source != null) ? " declared on " + source : ""; throw new AnnotationConfigurationException(String.format( - "Different @AliasFor mirror values for annotation [%s]%s, " - + "attribute '%s' and its alias '%s' are declared with values of [%s] and [%s].", + "Different @AliasFor mirror values for annotation [%s]%s, attribute '%s' " + + "and its alias '%s' are declared with values of [%s] and [%s].", getAnnotationType().getName(), on, attributes.get(result).getName(), attribute.getName(), @@ -664,8 +644,7 @@ final class AnnotationTypeMapping { int getAttributeIndex(int index) { return this.indexes[index]; } - } - } + } 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 b4ecef04223..2196847620d 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 @@ -118,17 +118,13 @@ abstract class AnnotationsScanner { switch (searchStrategy) { case DIRECT: - return processElement(context, source, - processor, classFilter); + return processElement(context, source, processor, classFilter); case INHERITED_ANNOTATIONS: - return processClassInheritedAnnotations(context, source, - processor, classFilter); + return processClassInheritedAnnotations(context, source, processor, classFilter); case SUPER_CLASS: - return processClassHierarchy(context, new int[] { 0 }, source, - processor, classFilter, false); + return processClassHierarchy(context, new int[] {0}, source, processor, classFilter, false); case EXHAUSTIVE: - return processClassHierarchy(context, new int[] { 0 }, source, - processor, classFilter, true); + return processClassHierarchy(context, new int[] {0}, source, processor, classFilter, true); } throw new IllegalStateException("Unsupported search strategy " + searchStrategy); } @@ -405,8 +401,8 @@ abstract class AnnotationsScanner { 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, @@ -426,7 +422,7 @@ abstract class AnnotationsScanner { static A getDeclaredAnnotation(AnnotatedElement source, Class annotationType) { Annotation[] annotations = getDeclaredAnnotations(source, false); for (Annotation annotation : annotations) { - if (annotation != null && annotationType.equals(annotation.annotationType())) { + if (annotation != null && annotationType == annotation.annotationType()) { return (A) annotation; } } @@ -500,9 +496,12 @@ abstract class AnnotationsScanner { else { return false; } + + if (type == Ordered.class) { + return true; + } String name = type.getName(); - return (type == Ordered.class || - name.startsWith("java") || + return (name.startsWith("java") || name.startsWith("org.springframework.lang.") || name.startsWith("org.springframework.util.") || (name.startsWith("com.sun") && !name.contains("Proxy"))); 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 2a2a38a5139..ad777666b79 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 @@ -111,8 +111,8 @@ public abstract class RepeatableContainers { * {@code repeatable}. * @return a {@link RepeatableContainers} instance */ - public static RepeatableContainers of(Class repeatable, - @Nullable Class container) { + public static RepeatableContainers of( + Class repeatable, @Nullable Class container) { return new ExplicitRepeatableContainer(null, repeatable, container); } @@ -133,13 +133,11 @@ public abstract class RepeatableContainers { */ private static class StandardRepeatableContainers extends RepeatableContainers { - private static final Map, Object> cache = - new ConcurrentReferenceHashMap<>(); + private static final Map, Object> cache = new ConcurrentReferenceHashMap<>(); private static final Object NONE = new Object(); - private static StandardRepeatableContainers INSTANCE = - new StandardRepeatableContainers(); + private static StandardRepeatableContainers INSTANCE = new StandardRepeatableContainers(); StandardRepeatableContainers() { super(null); @@ -156,17 +154,13 @@ public abstract class RepeatableContainers { } @Nullable - private static Method getRepeatedAnnotationsMethod( - Class annotationType) { - + private static Method getRepeatedAnnotationsMethod(Class annotationType) { Object result = cache.computeIfAbsent(annotationType, StandardRepeatableContainers::computeRepeatedAnnotationsMethod); - return result != NONE ? (Method) result : null; + return (result != NONE ? (Method) result : null); } - private static Object computeRepeatedAnnotationsMethod( - Class annotationType) { - + private static Object computeRepeatedAnnotationsMethod(Class annotationType) { AttributeMethods methods = AttributeMethods.forAnnotationType(annotationType); if (methods.isOnlyValueAttribute()) { Method method = methods.get("value"); @@ -176,15 +170,14 @@ public abstract class RepeatableContainers { Class returnType = method.getReturnType(); if (returnType.isArray()) { Class componentType = returnType.getComponentType(); - if (Annotation.class.isAssignableFrom(componentType) - && componentType.isAnnotationPresent(Repeatable.class)) { + if (Annotation.class.isAssignableFrom(componentType) && + componentType.isAnnotationPresent(Repeatable.class)) { return method; } } } return NONE; } - } 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 40b289a20c4..3d869c4d509 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 @@ -248,9 +248,8 @@ final class TypeMappedAnnotations implements MergedAnnotations { return null; } - static MergedAnnotations from(@Nullable AnnotatedElement element, - SearchStrategy searchStrategy, RepeatableContainers repeatableContainers, - AnnotationFilter annotationFilter) { + static MergedAnnotations from(@Nullable AnnotatedElement element, SearchStrategy searchStrategy, + RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { if (element == null || AnnotationsScanner.isKnownEmpty(element, searchStrategy, annotationFilter)) { return NONE; @@ -324,11 +323,11 @@ final class TypeMappedAnnotations implements MergedAnnotations { if (type == requiredType || type.getName().equals(requiredType)) { return Boolean.TRUE; } - Annotation[] repeatedAnnotations = this.repeatableContainers - .findRepeatedAnnotations(annotation); + Annotation[] repeatedAnnotations = + this.repeatableContainers.findRepeatedAnnotations(annotation); if (repeatedAnnotations != null) { - Boolean result = doWithAnnotations(requiredType, aggregateIndex, - source, repeatedAnnotations); + Boolean result = doWithAnnotations( + requiredType, aggregateIndex, source, repeatedAnnotations); if (result != null) { return result; } @@ -402,8 +401,7 @@ final class TypeMappedAnnotations implements MergedAnnotations { @Nullable Object source, Annotation[] annotations) { for (Annotation annotation : annotations) { - if (annotation != null && - !annotationFilter.matches(annotation)) { + if (annotation != null && !annotationFilter.matches(annotation)) { MergedAnnotation result = process(type, aggregateIndex, source, annotation); if (result != null) { return result; diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationIntrospectionFailureTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationIntrospectionFailureTests.java index 6822c4e3aa2..8b45d0bec48 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationIntrospectionFailureTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationIntrospectionFailureTests.java @@ -68,8 +68,7 @@ public class AnnotationIntrospectionFailureTests { assertThat(AnnotatedElementUtils.getMergedAnnotationAttributes( withExampleMetaAnnotation, exampleAnnotationClass)).isNull(); assertThat(AnnotatedElementUtils.getMergedAnnotationAttributes( - withExampleMetaAnnotation, - exampleMetaAnnotationClass)).isNull(); + withExampleMetaAnnotation, exampleMetaAnnotationClass)).isNull(); assertThat(AnnotatedElementUtils.hasAnnotation(withExampleMetaAnnotation, exampleAnnotationClass)).isFalse(); assertThat(AnnotatedElementUtils.hasAnnotation(withExampleMetaAnnotation, @@ -97,12 +96,10 @@ public class AnnotationIntrospectionFailureTests { static class FilteringClassLoader extends OverridingClassLoader { - FilteringClassLoader(ClassLoader parent) { super(parent); } - @Override protected boolean isEligibleForOverriding(String className) { return className.startsWith( @@ -110,36 +107,31 @@ public class AnnotationIntrospectionFailureTests { } @Override - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - if (name.startsWith(AnnotationIntrospectionFailureTests.class.getName()) - && name.contains("Filtered")) { + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (name.startsWith(AnnotationIntrospectionFailureTests.class.getName()) && + name.contains("Filtered")) { throw new ClassNotFoundException(name); } return super.loadClass(name, resolve); } - } static class FilteredType { - } @Retention(RetentionPolicy.RUNTIME) - static @interface ExampleAnnotation { + @interface ExampleAnnotation { Class value() default Void.class; - } @ExampleAnnotation(FilteredType.class) static class WithExampleAnnotation { - } @Retention(RetentionPolicy.RUNTIME) @ExampleAnnotation - static @interface ExampleMetaAnnotation { + @interface ExampleMetaAnnotation { @AliasFor(annotation = ExampleAnnotation.class, attribute = "value") Class example1() default Void.class; @@ -151,7 +143,6 @@ public class AnnotationIntrospectionFailureTests { @ExampleMetaAnnotation(example1 = FilteredType.class) static class WithExampleMetaAnnotation { - } }