Skip to content

Commit c30145d

Browse files
committed
MethodReference treats proxy-targeting expressions as non-compilable
Issue: SPR-16191
1 parent 7406f59 commit c30145d

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

+8-3
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;
@@ -260,7 +261,8 @@ public String toStringAST() {
260261
@Override
261262
public boolean isCompilable() {
262263
CachedMethodExecutor executorToCheck = this.cachedExecutor;
263-
if (executorToCheck == null || !(executorToCheck.get() instanceof ReflectiveMethodExecutor)) {
264+
if (executorToCheck == null || executorToCheck.hasProxyTarget() ||
265+
!(executorToCheck.get() instanceof ReflectiveMethodExecutor)) {
264266
return false;
265267
}
266268

@@ -274,8 +276,7 @@ public boolean isCompilable() {
274276
if (executor.didArgumentConversionOccur()) {
275277
return false;
276278
}
277-
Method method = executor.getMethod();
278-
Class<?> clazz = method.getDeclaringClass();
279+
Class<?> clazz = executor.getMethod().getDeclaringClass();
279280
if (!Modifier.isPublic(clazz.getModifiers()) && executor.getPublicDeclaringClass() == null) {
280281
return false;
281282
}
@@ -400,6 +401,10 @@ public boolean isSuitable(Object value, @Nullable TypeDescriptor target, List<Ty
400401
ObjectUtils.nullSafeEquals(this.target, target) && this.argumentTypes.equals(argumentTypes));
401402
}
402403

404+
public boolean hasProxyTarget() {
405+
return (this.target != null && Proxy.isProxyClass(this.target.getType()));
406+
}
407+
403408
public MethodExecutor get() {
404409
return this.methodExecutor;
405410
}

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

+20-1
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)