|
|
|
@ -22,8 +22,11 @@ import java.lang.reflect.Member; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.lang.reflect.Modifier; |
|
|
|
import java.lang.reflect.Modifier; |
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.Arrays; |
|
|
|
|
|
|
|
import java.util.Collections; |
|
|
|
import java.util.Comparator; |
|
|
|
import java.util.Comparator; |
|
|
|
|
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
import java.util.Set; |
|
|
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
|
import java.util.concurrent.ConcurrentHashMap; |
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.core.MethodParameter; |
|
|
|
import org.springframework.core.MethodParameter; |
|
|
|
@ -50,6 +53,17 @@ import org.springframework.util.StringUtils; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class ReflectivePropertyAccessor implements PropertyAccessor { |
|
|
|
public class ReflectivePropertyAccessor implements PropertyAccessor { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final Set<Class<?>> BOOLEAN_TYPES; |
|
|
|
|
|
|
|
static { |
|
|
|
|
|
|
|
Set<Class<?>> booleanTypes = new HashSet<Class<?>>(); |
|
|
|
|
|
|
|
booleanTypes.add(Boolean.class); |
|
|
|
|
|
|
|
booleanTypes.add(Boolean.TYPE); |
|
|
|
|
|
|
|
BOOLEAN_TYPES = Collections.unmodifiableSet(booleanTypes); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final Set<Class<?>> ANY_TYPES = Collections.emptySet(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Map<CacheKey, InvokerPair> readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>(64); |
|
|
|
private final Map<CacheKey, InvokerPair> readerCache = new ConcurrentHashMap<CacheKey, InvokerPair>(64); |
|
|
|
|
|
|
|
|
|
|
|
private final Map<CacheKey, Member> writerCache = new ConcurrentHashMap<CacheKey, Member>(64); |
|
|
|
private final Map<CacheKey, Member> writerCache = new ConcurrentHashMap<CacheKey, Member>(64); |
|
|
|
@ -319,8 +333,13 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { |
|
|
|
* Find a getter method for the specified property. |
|
|
|
* Find a getter method for the specified property. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) { |
|
|
|
protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) { |
|
|
|
return findMethodForProperty(getPropertyMethodSuffixes(propertyName), |
|
|
|
Method method = findMethodForProperty(getPropertyMethodSuffixes(propertyName), |
|
|
|
new String[] { "get", "is" }, clazz, mustBeStatic, 0); |
|
|
|
"get", clazz, mustBeStatic, 0, ANY_TYPES); |
|
|
|
|
|
|
|
if (method == null) { |
|
|
|
|
|
|
|
method = findMethodForProperty(getPropertyMethodSuffixes(propertyName), |
|
|
|
|
|
|
|
"is", clazz, mustBeStatic, 0, BOOLEAN_TYPES); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return method; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -328,20 +347,19 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected Method findSetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) { |
|
|
|
protected Method findSetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) { |
|
|
|
return findMethodForProperty(getPropertyMethodSuffixes(propertyName), |
|
|
|
return findMethodForProperty(getPropertyMethodSuffixes(propertyName), |
|
|
|
new String[] { "set" }, clazz, mustBeStatic, 1); |
|
|
|
"set", clazz, mustBeStatic, 1, ANY_TYPES); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Method findMethodForProperty(String[] methodSuffixes, String[] prefixes, Class<?> clazz, |
|
|
|
private Method findMethodForProperty(String[] methodSuffixes, String prefix, Class<?> clazz, |
|
|
|
boolean mustBeStatic, int numberOfParams) { |
|
|
|
boolean mustBeStatic, int numberOfParams, Set<Class<?>> requiredReturnTypes) { |
|
|
|
Method[] methods = getSortedClassMethods(clazz); |
|
|
|
Method[] methods = getSortedClassMethods(clazz); |
|
|
|
for (String methodSuffix : methodSuffixes) { |
|
|
|
for (String methodSuffix : methodSuffixes) { |
|
|
|
for (String prefix : prefixes) { |
|
|
|
for (Method method : methods) { |
|
|
|
for (Method method : methods) { |
|
|
|
if (method.getName().equals(prefix + methodSuffix) |
|
|
|
if (method.getName().equals(prefix + methodSuffix) |
|
|
|
&& method.getParameterTypes().length == numberOfParams |
|
|
|
&& method.getParameterTypes().length == numberOfParams |
|
|
|
&& (!mustBeStatic || Modifier.isStatic(method.getModifiers())) |
|
|
|
&& (!mustBeStatic || Modifier.isStatic(method.getModifiers()))) { |
|
|
|
&& (requiredReturnTypes.isEmpty() || requiredReturnTypes.contains(method.getReturnType()))) { |
|
|
|
return method; |
|
|
|
return method; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|