Skip to content

Commit 4c5e17e

Browse files
committed
Consistent resolution of Class methods and static methods
Issue: SPR-12502 (cherry picked from commit 9ef0bdc)
1 parent 9413204 commit 4c5e17e

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,12 +17,13 @@
1717
package org.springframework.expression.spel.support;
1818

1919
import java.lang.reflect.Method;
20+
import java.lang.reflect.Modifier;
2021
import java.util.ArrayList;
2122
import java.util.Arrays;
23+
import java.util.Collection;
2224
import java.util.Collections;
2325
import java.util.Comparator;
2426
import java.util.HashMap;
25-
import java.util.HashSet;
2627
import java.util.LinkedHashSet;
2728
import java.util.List;
2829
import java.util.Map;
@@ -106,7 +107,7 @@ public MethodExecutor resolve(EvaluationContext context, Object targetObject, St
106107
try {
107108
TypeConverter typeConverter = context.getTypeConverter();
108109
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
109-
List<Method> methods = new ArrayList<Method>(Arrays.asList(getMethods(type, targetObject)));
110+
List<Method> methods = new ArrayList<Method>((getMethods(type, targetObject)));
110111

111112
// If a filter is registered for this type, call it
112113
MethodFilter filter = (this.filters != null ? this.filters.get(type) : null);
@@ -201,14 +202,22 @@ else if (matchRequiringConversion != null) {
201202
}
202203
}
203204

204-
private Method[] getMethods(Class<?> type, Object targetObject) {
205+
private Collection<Method> getMethods(Class<?> type, Object targetObject) {
205206
if (targetObject instanceof Class) {
206-
Set<Method> methods = new HashSet<Method>();
207-
methods.addAll(Arrays.asList(getMethods(type)));
208-
methods.addAll(Arrays.asList(getMethods(targetObject.getClass())));
209-
return methods.toArray(new Method[methods.size()]);
207+
Set<Method> result = new LinkedHashSet<Method>();
208+
result.addAll(Arrays.asList(getMethods(targetObject.getClass())));
209+
// Add these also so that static result are invocable on the type: e.g. Float.valueOf(..)
210+
Method[] methods = getMethods(type);
211+
for (Method method : methods) {
212+
if (Modifier.isStatic(method.getModifiers())) {
213+
result.add(method);
214+
}
215+
}
216+
return result;
217+
}
218+
else {
219+
return Arrays.asList(getMethods(type));
210220
}
211-
return getMethods(type);
212221
}
213222

214223
/**

spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,14 @@ public void SPR11609() {
18351835
assertEquals(1, exp.getValue(sec));
18361836
}
18371837

1838+
@Test
1839+
public void SPR12502() throws Exception {
1840+
SpelExpressionParser parser = new SpelExpressionParser();
1841+
Expression expression = parser.parseExpression("#root.getClass().getName()");
1842+
assertEquals(UnnamedUser.class.getName(), expression.getValue(new UnnamedUser()));
1843+
assertEquals(NamedUser.class.getName(), expression.getValue(new NamedUser()));
1844+
}
1845+
18381846

18391847
private static enum ABC { A, B, C }
18401848

@@ -1976,4 +1984,16 @@ public static class MapWithConstant extends HashMap {
19761984
public static final int X = 1;
19771985
}
19781986

1987+
1988+
public static class UnnamedUser {
1989+
}
1990+
1991+
1992+
public static class NamedUser {
1993+
1994+
public String getName() {
1995+
return "foo";
1996+
}
1997+
}
1998+
19791999
}

0 commit comments

Comments
 (0)