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 @@ @@ -17,17 +17,19 @@
package org.springframework.expression.spel.support;
import java.lang.reflect.Constructor;
import java.util.List;
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.ConstructorExecutor;
import org.springframework.expression.ConstructorResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
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
@ -49,13 +51,24 @@ public class ReflectiveConstructorResolver implements ConstructorResolver { @@ -49,13 +51,24 @@ public class ReflectiveConstructorResolver implements ConstructorResolver {
*/
public ConstructorExecutor resolve(EvaluationContext context, String typename, List<TypeDescriptor> argumentTypes)
throws AccessException {
try {
TypeConverter typeConverter = context.getTypeConverter();
Class<?> type = context.getTypeLocator().findType(typename);
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;
int[] argsToConvert = null;
Constructor matchRequiringConversion = null;
for (Constructor ctor : ctors) {
Class[] paramTypes = ctor.getParameterTypes();
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; @@ -18,6 +18,8 @@ package org.springframework.expression.spel.support;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -33,11 +35,13 @@ import org.springframework.expression.MethodResolver; @@ -33,11 +35,13 @@ import org.springframework.expression.MethodResolver;
import org.springframework.expression.TypeConverter;
import org.springframework.expression.spel.SpelEvaluationException;
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.
*
* @author Andy Clement
* @author Juergen Hoeller
* @since 3.0
*/
public class ReflectiveMethodResolver implements MethodResolver {
@ -58,31 +62,41 @@ public class ReflectiveMethodResolver implements MethodResolver { @@ -58,31 +62,41 @@ public class ReflectiveMethodResolver implements MethodResolver {
*/
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name,
List<TypeDescriptor> argumentTypes) throws AccessException {
try {
TypeConverter typeConverter = context.getTypeConverter();
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
Method[] methods = type.getMethods();
// If a filter is registered for this type, call it
MethodFilter methodfilter = (filters==null?null:filters.get(type));
if (methodfilter!=null) {
MethodFilter filter = (this.filters != null ? this.filters.get(type) : null);
if (filter != null) {
List<Method> methodsForFiltering = new ArrayList<Method>();
for (Method method: methods) {
methodsForFiltering.add(method);
}
List<Method> methodsFiltered = methodfilter.filter(methodsForFiltering);
if (methodsFiltered == null || methodsFiltered.size()==0) {
List<Method> methodsFiltered = filter.filter(methodsForFiltering);
if (CollectionUtils.isEmpty(methodsFiltered)) {
methods = NO_METHODS;
}
else {
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;
int[] argsToConvert = null;
boolean multipleOptions = false;
Method matchRequiringConversion = null;
boolean multipleOptions = false;
for (Method method : methods) {
if (method.isBridge()) {
continue;
@ -139,7 +153,7 @@ public class ReflectiveMethodResolver implements MethodResolver { @@ -139,7 +153,7 @@ public class ReflectiveMethodResolver implements MethodResolver {
public void registerMethodFilter(Class<?> type, MethodFilter filter) {
if (this.filters == null) {
this.filters = new HashMap<Class<?>,MethodFilter>();
this.filters = new HashMap<Class<?>, MethodFilter>();
}
if (filter == null) {
this.filters.remove(type);

Loading…
Cancel
Save