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 19a3189564..657e34d5a5 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 @@ -28,7 +28,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.BiFunction; import org.springframework.core.annotation.AnnotationTypeMapping.MirrorSets.MirrorSet; import org.springframework.lang.Nullable; @@ -465,8 +464,7 @@ final class AnnotationTypeMapping { * nested annotations * @return {@code true} if the value is equivalent to the default value */ - boolean isEquivalentToDefaultValue(int attributeIndex, Object value, - BiFunction valueExtractor) { + boolean isEquivalentToDefaultValue(int attributeIndex, Object value, ValueExtractor valueExtractor) { Method attribute = this.attributes.get(attributeIndex); return isEquivalentToDefaultValue(attribute, value, valueExtractor); @@ -488,13 +486,13 @@ final class AnnotationTypeMapping { } private static boolean isEquivalentToDefaultValue(Method attribute, Object value, - BiFunction valueExtractor) { + ValueExtractor valueExtractor) { return areEquivalent(attribute.getDefaultValue(), value, valueExtractor); } private static boolean areEquivalent(@Nullable Object value, @Nullable Object extractedValue, - BiFunction valueExtractor) { + ValueExtractor valueExtractor) { if (ObjectUtils.nullSafeEquals(value, extractedValue)) { return true; @@ -528,7 +526,7 @@ final class AnnotationTypeMapping { } private static boolean areEquivalent(Annotation annotation, @Nullable Object extractedValue, - BiFunction valueExtractor) { + ValueExtractor valueExtractor) { AttributeMethods attributes = AttributeMethods.forAnnotationType(annotation.annotationType()); for (int i = 0; i < attributes.size(); i++) { @@ -539,7 +537,7 @@ final class AnnotationTypeMapping { value2 = ((TypeMappedAnnotation) extractedValue).getValue(attribute.getName()).orElse(null); } else { - value2 = valueExtractor.apply(attribute, extractedValue); + value2 = valueExtractor.extract(attribute, extractedValue); } if (!areEquivalent(value1, value2, valueExtractor)) { return false; @@ -603,9 +601,7 @@ final class AnnotationTypeMapping { return this.assigned[attributeIndex]; } - int[] resolve(@Nullable Object source, @Nullable Object annotation, - BiFunction valueExtractor) { - + int[] resolve(@Nullable Object source, @Nullable Object annotation, ValueExtractor valueExtractor) { int[] result = new int[attributes.size()]; for (int i = 0; i < result.length; i++) { result[i] = i; @@ -641,14 +637,12 @@ final class AnnotationTypeMapping { } } - int resolve(@Nullable Object source, @Nullable A annotation, - BiFunction valueExtractor) { - + int resolve(@Nullable Object source, @Nullable A annotation, ValueExtractor valueExtractor) { int result = -1; Object lastValue = null; for (int i = 0; i < this.size; i++) { Method attribute = attributes.get(this.indexes[i]); - Object value = valueExtractor.apply(attribute, annotation); + Object value = valueExtractor.extract(attribute, annotation); boolean isDefaultValue = (value == null || isEquivalentToDefaultValue(attribute, value, valueExtractor)); if (isDefaultValue || ObjectUtils.nullSafeEquals(lastValue, value)) { 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 cc612a1b9b..68a67ea7bc 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 @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; -import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; @@ -64,6 +63,7 @@ import org.springframework.util.ReflectionUtils; * * @author Phillip Webb * @author Juergen Hoeller + * @author Sam Brannen * @since 5.2 * @param the annotation type * @see TypeMappedAnnotations @@ -96,7 +96,7 @@ final class TypeMappedAnnotation extends AbstractMergedAnn @Nullable private final Object rootAttributes; - private final BiFunction valueExtractor; + private final ValueExtractor valueExtractor; private final int aggregateIndex; @@ -114,16 +114,15 @@ final class TypeMappedAnnotation extends AbstractMergedAnn private TypeMappedAnnotation(AnnotationTypeMapping mapping, @Nullable ClassLoader classLoader, - @Nullable Object source, @Nullable Object rootAttributes, - BiFunction valueExtractor, int aggregateIndex) { + @Nullable Object source, @Nullable Object rootAttributes, ValueExtractor valueExtractor, + int aggregateIndex) { this(mapping, classLoader, source, rootAttributes, valueExtractor, aggregateIndex, null); } private TypeMappedAnnotation(AnnotationTypeMapping mapping, @Nullable ClassLoader classLoader, - @Nullable Object source, @Nullable Object rootAttributes, - BiFunction valueExtractor, int aggregateIndex, - @Nullable int[] resolvedRootMirrors) { + @Nullable Object source, @Nullable Object rootAttributes, ValueExtractor valueExtractor, + int aggregateIndex, @Nullable int[] resolvedRootMirrors) { this.mapping = mapping; this.classLoader = classLoader; @@ -140,9 +139,8 @@ final class TypeMappedAnnotation extends AbstractMergedAnn } private TypeMappedAnnotation(AnnotationTypeMapping mapping, @Nullable ClassLoader classLoader, - @Nullable Object source, @Nullable Object rootAnnotation, - BiFunction valueExtractor, int aggregateIndex, - boolean useMergedValues, @Nullable Predicate attributeFilter, + @Nullable Object source, @Nullable Object rootAnnotation, ValueExtractor valueExtractor, + int aggregateIndex, boolean useMergedValues, @Nullable Predicate attributeFilter, int[] resolvedRootMirrors, int[] resolvedMirrors) { this.classLoader = classLoader; @@ -426,7 +424,7 @@ final class TypeMappedAnnotation extends AbstractMergedAnn } if (mapping.getDistance() == 0) { Method attribute = mapping.getAttributes().get(attributeIndex); - Object result = this.valueExtractor.apply(attribute, this.rootAttributes); + Object result = this.valueExtractor.extract(attribute, this.rootAttributes); return (result != null) ? result : attribute.getDefaultValue(); } return getValueFromMetaAnnotation(attributeIndex, forMirrorResolution); @@ -562,7 +560,7 @@ final class TypeMappedAnnotation extends AbstractMergedAnn mapping, null, this.source, value, getValueExtractor(value), this.aggregateIndex); } - private BiFunction getValueExtractor(Object value) { + private ValueExtractor getValueExtractor(Object value) { if (value instanceof Annotation) { return ReflectionUtils::invokeMethod; } @@ -664,8 +662,7 @@ final class TypeMappedAnnotation extends AbstractMergedAnn @Nullable private static TypeMappedAnnotation createIfPossible( AnnotationTypeMapping mapping, @Nullable Object source, @Nullable Object rootAttribute, - BiFunction valueExtractor, - int aggregateIndex, IntrospectionFailureLogger logger) { + ValueExtractor valueExtractor, int aggregateIndex, IntrospectionFailureLogger logger) { try { return new TypeMappedAnnotation<>(mapping, null, source, rootAttribute, diff --git a/spring-core/src/main/java/org/springframework/core/annotation/ValueExtractor.java b/spring-core/src/main/java/org/springframework/core/annotation/ValueExtractor.java new file mode 100644 index 0000000000..62438f629b --- /dev/null +++ b/spring-core/src/main/java/org/springframework/core/annotation/ValueExtractor.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.core.annotation; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.Map; + +import org.springframework.lang.Nullable; + +/** + * Strategy API for extracting a value for an annotation attribute from a given + * source object which is typically an {@link Annotation}, {@link Map}, or + * {@link TypeMappedAnnotation}. + * + * @since 5.2.4 + * @author Sam Brannen + */ +@FunctionalInterface +interface ValueExtractor { + + /** + * Extract the annotation attribute represented by the supplied {@link Method} + * from the supplied source {@link Object}. + */ + @Nullable + Object extract(Method attribute, @Nullable Object object); + +}