diff --git a/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java b/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java index 5584284cd3b..cef40a25ee5 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java +++ b/spring-core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java @@ -17,8 +17,8 @@ package org.springframework.core.convert.support; import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Collections; @@ -71,8 +71,9 @@ import org.springframework.util.ReflectionUtils; */ final class ObjectToObjectConverter implements ConditionalGenericConverter { - // Cache for the latest to-method resolved on a given Class - private static final Map, Member> conversionMemberCache = + // Cache for the latest to-method, static factory method, or factory constructor + // resolved on a given Class + private static final Map, Executable> conversionExecutableCache = new ConcurrentReferenceHashMap<>(32); @@ -95,11 +96,11 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter { } Class sourceClass = sourceType.getType(); Class targetClass = targetType.getType(); - Member member = getValidatedMember(targetClass, sourceClass); + Executable executable = getValidatedExecutable(targetClass, sourceClass); try { - if (member instanceof Method) { - Method method = (Method) member; + if (executable instanceof Method) { + Method method = (Method) executable; ReflectionUtils.makeAccessible(method); if (!Modifier.isStatic(method.getModifiers())) { return method.invoke(source); @@ -108,8 +109,8 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter { return method.invoke(null, source); } } - else if (member instanceof Constructor) { - Constructor ctor = (Constructor) member; + else if (executable instanceof Constructor) { + Constructor ctor = (Constructor) executable; ReflectionUtils.makeAccessible(ctor); return ctor.newInstance(source); } @@ -130,42 +131,41 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter { } - static boolean hasConversionMethodOrConstructor(Class targetClass, Class sourceClass) { - return (getValidatedMember(targetClass, sourceClass) != null); + return (getValidatedExecutable(targetClass, sourceClass) != null); } @Nullable - private static Member getValidatedMember(Class targetClass, Class sourceClass) { - Member member = conversionMemberCache.get(targetClass); - if (isApplicable(member, sourceClass)) { - return member; + private static Executable getValidatedExecutable(Class targetClass, Class sourceClass) { + Executable executable = conversionExecutableCache.get(targetClass); + if (isApplicable(executable, sourceClass)) { + return executable; } - member = determineToMethod(targetClass, sourceClass); - if (member == null) { - member = determineFactoryMethod(targetClass, sourceClass); - if (member == null) { - member = determineFactoryConstructor(targetClass, sourceClass); - if (member == null) { + executable = determineToMethod(targetClass, sourceClass); + if (executable == null) { + executable = determineFactoryMethod(targetClass, sourceClass); + if (executable == null) { + executable = determineFactoryConstructor(targetClass, sourceClass); + if (executable == null) { return null; } } } - conversionMemberCache.put(targetClass, member); - return member; + conversionExecutableCache.put(targetClass, executable); + return executable; } - private static boolean isApplicable(Member member, Class sourceClass) { - if (member instanceof Method) { - Method method = (Method) member; + private static boolean isApplicable(Executable executable, Class sourceClass) { + if (executable instanceof Method) { + Method method = (Method) executable; return (!Modifier.isStatic(method.getModifiers()) ? ClassUtils.isAssignable(method.getDeclaringClass(), sourceClass) : method.getParameterTypes()[0] == sourceClass); } - else if (member instanceof Constructor) { - Constructor ctor = (Constructor) member; + else if (executable instanceof Constructor) { + Constructor ctor = (Constructor) executable; return (ctor.getParameterTypes()[0] == sourceClass); } else {