Browse Source

SpEL method invocations prefer method with fewest parameters (e.g. no-arg over vararg; SPR-7633)

pull/1234/head
Juergen Hoeller 15 years ago
parent
commit
7553b76f15
  1. 19
      org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorResolver.java
  2. 28
      org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java

19
org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorResolver.java

@ -17,17 +17,19 @@
package org.springframework.expression.spel.support; package org.springframework.expression.spel.support;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.AccessException; import org.springframework.expression.AccessException;
import org.springframework.expression.ConstructorExecutor; import org.springframework.expression.ConstructorExecutor;
import org.springframework.expression.ConstructorResolver; import org.springframework.expression.ConstructorResolver;
import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException; import org.springframework.expression.EvaluationException;
import org.springframework.expression.TypeConverter; import org.springframework.expression.TypeConverter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.MethodParameter;
/** /**
* A constructor resolver that uses reflection to locate the constructor that should be invoked * A constructor resolver that uses reflection to locate the constructor that should be invoked
@ -49,13 +51,24 @@ public class ReflectiveConstructorResolver implements ConstructorResolver {
*/ */
public ConstructorExecutor resolve(EvaluationContext context, String typename, List<TypeDescriptor> argumentTypes) public ConstructorExecutor resolve(EvaluationContext context, String typename, List<TypeDescriptor> argumentTypes)
throws AccessException { throws AccessException {
try { try {
TypeConverter typeConverter = context.getTypeConverter(); TypeConverter typeConverter = context.getTypeConverter();
Class<?> type = context.getTypeLocator().findType(typename); Class<?> type = context.getTypeLocator().findType(typename);
Constructor[] ctors = type.getConstructors(); Constructor[] ctors = type.getConstructors();
Arrays.sort(ctors, new Comparator<Constructor>() {
public int compare(Constructor c1, Constructor c2) {
int c1pl = c1.getParameterTypes().length;
int c2pl = c2.getParameterTypes().length;
return (new Integer(c1pl)).compareTo(c2pl);
}
});
Constructor closeMatch = null; Constructor closeMatch = null;
int[] argsToConvert = null; int[] argsToConvert = null;
Constructor matchRequiringConversion = null; Constructor matchRequiringConversion = null;
for (Constructor ctor : ctors) { for (Constructor ctor : ctors) {
Class[] paramTypes = ctor.getParameterTypes(); Class[] paramTypes = ctor.getParameterTypes();
List<TypeDescriptor> paramDescriptors = new ArrayList<TypeDescriptor>(paramTypes.length); List<TypeDescriptor> paramDescriptors = new ArrayList<TypeDescriptor>(paramTypes.length);

28
org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java

@ -18,6 +18,8 @@ package org.springframework.expression.spel.support;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -33,11 +35,13 @@ import org.springframework.expression.MethodResolver;
import org.springframework.expression.TypeConverter; import org.springframework.expression.TypeConverter;
import org.springframework.expression.spel.SpelEvaluationException; import org.springframework.expression.spel.SpelEvaluationException;
import org.springframework.expression.spel.SpelMessage; import org.springframework.expression.spel.SpelMessage;
import org.springframework.util.CollectionUtils;
/** /**
* A method resolver that uses reflection to locate the method that should be invoked. * A method resolver that uses reflection to locate the method that should be invoked.
* *
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
*/ */
public class ReflectiveMethodResolver implements MethodResolver { public class ReflectiveMethodResolver implements MethodResolver {
@ -58,31 +62,41 @@ public class ReflectiveMethodResolver implements MethodResolver {
*/ */
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name,
List<TypeDescriptor> argumentTypes) throws AccessException { List<TypeDescriptor> argumentTypes) throws AccessException {
try { try {
TypeConverter typeConverter = context.getTypeConverter(); TypeConverter typeConverter = context.getTypeConverter();
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass()); Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
Method[] methods = type.getMethods(); Method[] methods = type.getMethods();
// If a filter is registered for this type, call it // If a filter is registered for this type, call it
MethodFilter methodfilter = (filters==null?null:filters.get(type)); MethodFilter filter = (this.filters != null ? this.filters.get(type) : null);
if (methodfilter!=null) { if (filter != null) {
List<Method> methodsForFiltering = new ArrayList<Method>(); List<Method> methodsForFiltering = new ArrayList<Method>();
for (Method method: methods) { for (Method method: methods) {
methodsForFiltering.add(method); methodsForFiltering.add(method);
} }
List<Method> methodsFiltered = methodfilter.filter(methodsForFiltering); List<Method> methodsFiltered = filter.filter(methodsForFiltering);
if (methodsFiltered == null || methodsFiltered.size()==0) { if (CollectionUtils.isEmpty(methodsFiltered)) {
methods = NO_METHODS; methods = NO_METHODS;
} }
else { else {
methods = methodsFiltered.toArray(new Method[methodsFiltered.size()]); methods = methodsFiltered.toArray(new Method[methodsFiltered.size()]);
} }
} }
Arrays.sort(methods, new Comparator<Method>() {
public int compare(Method m1, Method m2) {
int m1pl = m1.getParameterTypes().length;
int m2pl = m2.getParameterTypes().length;
return (new Integer(m1pl)).compareTo(m2pl);
}
});
Method closeMatch = null; Method closeMatch = null;
int[] argsToConvert = null; int[] argsToConvert = null;
boolean multipleOptions = false;
Method matchRequiringConversion = null; Method matchRequiringConversion = null;
boolean multipleOptions = false;
for (Method method : methods) { for (Method method : methods) {
if (method.isBridge()) { if (method.isBridge()) {
continue; continue;
@ -139,7 +153,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
public void registerMethodFilter(Class<?> type, MethodFilter filter) { public void registerMethodFilter(Class<?> type, MethodFilter filter) {
if (this.filters == null) { if (this.filters == null) {
this.filters = new HashMap<Class<?>,MethodFilter>(); this.filters = new HashMap<Class<?>, MethodFilter>();
} }
if (filter == null) { if (filter == null) {
this.filters.remove(type); this.filters.remove(type);

Loading…
Cancel
Save