Skip to content

Commit 6dc7346

Browse files
committed
MethodReference treats proxy-targeting expressions as non-compilable
Issue: SPR-16191 (cherry picked from commit c30145d)
1 parent 59d654b commit 6dc7346

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.lang.reflect.InvocationTargetException;
2020
import java.lang.reflect.Method;
2121
import java.lang.reflect.Modifier;
22+
import java.lang.reflect.Proxy;
2223
import java.util.ArrayList;
2324
import java.util.Collections;
2425
import java.util.List;
@@ -257,7 +258,8 @@ public String toStringAST() {
257258
@Override
258259
public boolean isCompilable() {
259260
CachedMethodExecutor executorToCheck = this.cachedExecutor;
260-
if (executorToCheck == null || !(executorToCheck.get() instanceof ReflectiveMethodExecutor)) {
261+
if (executorToCheck == null || executorToCheck.hasProxyTarget() ||
262+
!(executorToCheck.get() instanceof ReflectiveMethodExecutor)) {
261263
return false;
262264
}
263265

@@ -271,8 +273,7 @@ public boolean isCompilable() {
271273
if (executor.didArgumentConversionOccur()) {
272274
return false;
273275
}
274-
Method method = executor.getMethod();
275-
Class<?> clazz = method.getDeclaringClass();
276+
Class<?> clazz = executor.getMethod().getDeclaringClass();
276277
if (!Modifier.isPublic(clazz.getModifiers()) && executor.getPublicDeclaringClass() == null) {
277278
return false;
278279
}
@@ -385,6 +386,10 @@ public boolean isSuitable(Object value, TypeDescriptor target, List<TypeDescript
385386
this.target.equals(target) && this.argumentTypes.equals(argumentTypes));
386387
}
387388

389+
public boolean hasProxyTarget() {
390+
return (this.target != null && Proxy.isProxyClass(this.target.getType()));
391+
}
392+
388393
public MethodExecutor get() {
389394
return this.methodExecutor;
390395
}

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,13 +724,32 @@ public void varargsAgainstProxy_SPR16122() {
724724

725725
VarargsReceiver receiver = new VarargsReceiver();
726726
VarargsInterface proxy = (VarargsInterface) Proxy.newProxyInstance(
727-
getClass().getClassLoader(), new Class<?>[]{VarargsInterface.class},
727+
getClass().getClassLoader(), new Class<?>[] {VarargsInterface.class},
728728
(proxy1, method, args) -> method.invoke(receiver, args));
729729

730730
assertEquals("OK", expr.getValue(new StandardEvaluationContext(receiver)));
731731
assertEquals("OK", expr.getValue(new StandardEvaluationContext(proxy)));
732732
}
733733

734+
@Test
735+
public void testCompiledExpressionForProxy_SPR16191() {
736+
SpelExpressionParser expressionParser =
737+
new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null));
738+
Expression expression = expressionParser.parseExpression("#target.process(#root)");
739+
740+
VarargsReceiver receiver = new VarargsReceiver();
741+
VarargsInterface proxy = (VarargsInterface) Proxy.newProxyInstance(
742+
getClass().getClassLoader(), new Class<?>[] {VarargsInterface.class},
743+
(proxy1, method, args) -> method.invoke(receiver, args));
744+
745+
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
746+
evaluationContext.setVariable("target", proxy);
747+
748+
String result = expression.getValue(evaluationContext, "foo", String.class);
749+
result = expression.getValue(evaluationContext, "foo", String.class);
750+
assertEquals("OK", result);
751+
}
752+
734753
@Test
735754
public void varargsAndPrimitives_SPR8174() throws Exception {
736755
EvaluationContext emptyEvalContext = new StandardEvaluationContext();

0 commit comments

Comments
 (0)