@ -17,8 +17,8 @@
@@ -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;
@@ -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 < Class < ? > , Member > conversionMemberCache =
// Cache for the latest to-method, static factory method, or factory constructor
// resolved on a given Class
private static final Map < Class < ? > , Executable > conversionExecutableCache =
new ConcurrentReferenceHashMap < > ( 32 ) ;
@ -95,11 +96,11 @@ final class ObjectToObjectConverter implements ConditionalGenericConverter {
@@ -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 {
@@ -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 {
@@ -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 = conversionMember Cache. get ( targetClass ) ;
if ( isApplicable ( member , sourceClass ) ) {
return member ;
private static Executable getValidatedExecutable ( Class < ? > targetClass , Class < ? > sourceClass ) {
Executable executable = conversionExecutable Cache. 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 ;
}
}
}
conversionMember Cache . put ( targetClass , member ) ;
return member ;
conversionExecutable Cache . 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 {