Skip to content

Commit 97b5af8

Browse files
mrcoffee77sbrannen
authored andcommitted
Ensure methods declared in Object can be invoked on a JDK proxy in SpEL
This commit ensures that methods declared in java.lang.Object (such as toString() can be invoked on a JDK proxy instance in a SpEL expression. Closes gh-25316
1 parent 4751769 commit 97b5af8

File tree

2 files changed

+25
-12
lines changed

2 files changed

+25
-12
lines changed

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,7 @@
1919
import java.lang.reflect.Method;
2020
import java.lang.reflect.Modifier;
2121
import java.lang.reflect.Proxy;
22-
import java.util.ArrayList;
23-
import java.util.Collections;
24-
import java.util.HashMap;
25-
import java.util.LinkedHashSet;
26-
import java.util.List;
27-
import java.util.Map;
28-
import java.util.Set;
22+
import java.util.*;
2923

3024
import org.springframework.core.BridgeMethodResolver;
3125
import org.springframework.core.MethodParameter;
@@ -266,7 +260,13 @@ else if (Proxy.isProxyClass(type)) {
266260
* @since 3.1.1
267261
*/
268262
protected Method[] getMethods(Class<?> type) {
269-
return type.getMethods();
263+
Set<Method> methods=new HashSet<>();
264+
methods.addAll(Arrays.asList(type.getMethods()));
265+
//Add all methods of Object to have methods like toString on Proxy-Objects
266+
methods.addAll(Arrays.asList(Object.class.getMethods()));
267+
268+
Method[] methods1 = methods.toArray(new Method[0]);
269+
return methods1;
270270
}
271271

272272
/**

spring-expression/src/test/java/org/springframework/expression/spel/support/ReflectionHelperTests.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,21 @@
1818

1919
import java.io.ByteArrayOutputStream;
2020
import java.io.PrintStream;
21+
import java.lang.reflect.InvocationHandler;
2122
import java.lang.reflect.Method;
23+
import java.lang.reflect.Proxy;
2224
import java.util.ArrayList;
2325
import java.util.List;
2426

2527
import org.junit.jupiter.api.Test;
2628

2729
import org.springframework.core.convert.TypeDescriptor;
28-
import org.springframework.expression.EvaluationContext;
29-
import org.springframework.expression.ParseException;
30-
import org.springframework.expression.PropertyAccessor;
31-
import org.springframework.expression.TypedValue;
30+
import org.springframework.expression.*;
3231
import org.springframework.expression.spel.AbstractExpressionTests;
3332
import org.springframework.expression.spel.SpelUtilities;
3433
import org.springframework.expression.spel.standard.SpelExpression;
3534
import org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMatchKind;
35+
import org.springframework.util.Assert;
3636

3737
import static org.assertj.core.api.Assertions.assertThat;
3838
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -364,6 +364,19 @@ public void testOptimalReflectivePropertyAccessor() throws Exception {
364364
field.write(ctx, tester, "field", null));
365365
}
366366

367+
@Test
368+
void testReflectiveMethodResolver() throws AccessException {
369+
MethodResolver resolver=new ReflectiveMethodResolver();
370+
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
371+
Object obj= Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class<?>[]{Runnable.class}, new InvocationHandler() {
372+
@Override
373+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
374+
return null;
375+
}
376+
});
377+
MethodExecutor mexec=resolver.resolve(evaluationContext,obj,"toString",new ArrayList<>());
378+
Assert.notNull(mexec,"MethodExecutor should not be empty.");
379+
}
367380

368381
/**
369382
* Used to validate the match returned from a compareArguments call.

0 commit comments

Comments
 (0)