MethodReference treats proxy-targeting expressions as non-compilable
Issue: SPR-16191
This commit is contained in:
@@ -19,6 +19,7 @@ package org.springframework.expression.spel.ast;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -260,7 +261,8 @@ public class MethodReference extends SpelNodeImpl {
|
|||||||
@Override
|
@Override
|
||||||
public boolean isCompilable() {
|
public boolean isCompilable() {
|
||||||
CachedMethodExecutor executorToCheck = this.cachedExecutor;
|
CachedMethodExecutor executorToCheck = this.cachedExecutor;
|
||||||
if (executorToCheck == null || !(executorToCheck.get() instanceof ReflectiveMethodExecutor)) {
|
if (executorToCheck == null || executorToCheck.hasProxyTarget() ||
|
||||||
|
!(executorToCheck.get() instanceof ReflectiveMethodExecutor)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +276,7 @@ public class MethodReference extends SpelNodeImpl {
|
|||||||
if (executor.didArgumentConversionOccur()) {
|
if (executor.didArgumentConversionOccur()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Method method = executor.getMethod();
|
Class<?> clazz = executor.getMethod().getDeclaringClass();
|
||||||
Class<?> clazz = method.getDeclaringClass();
|
|
||||||
if (!Modifier.isPublic(clazz.getModifiers()) && executor.getPublicDeclaringClass() == null) {
|
if (!Modifier.isPublic(clazz.getModifiers()) && executor.getPublicDeclaringClass() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -400,6 +401,10 @@ public class MethodReference extends SpelNodeImpl {
|
|||||||
ObjectUtils.nullSafeEquals(this.target, target) && this.argumentTypes.equals(argumentTypes));
|
ObjectUtils.nullSafeEquals(this.target, target) && this.argumentTypes.equals(argumentTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasProxyTarget() {
|
||||||
|
return (this.target != null && Proxy.isProxyClass(this.target.getType()));
|
||||||
|
}
|
||||||
|
|
||||||
public MethodExecutor get() {
|
public MethodExecutor get() {
|
||||||
return this.methodExecutor;
|
return this.methodExecutor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -724,13 +724,32 @@ public class SpelReproTests extends AbstractExpressionTests {
|
|||||||
|
|
||||||
VarargsReceiver receiver = new VarargsReceiver();
|
VarargsReceiver receiver = new VarargsReceiver();
|
||||||
VarargsInterface proxy = (VarargsInterface) Proxy.newProxyInstance(
|
VarargsInterface proxy = (VarargsInterface) Proxy.newProxyInstance(
|
||||||
getClass().getClassLoader(), new Class<?>[]{VarargsInterface.class},
|
getClass().getClassLoader(), new Class<?>[] {VarargsInterface.class},
|
||||||
(proxy1, method, args) -> method.invoke(receiver, args));
|
(proxy1, method, args) -> method.invoke(receiver, args));
|
||||||
|
|
||||||
assertEquals("OK", expr.getValue(new StandardEvaluationContext(receiver)));
|
assertEquals("OK", expr.getValue(new StandardEvaluationContext(receiver)));
|
||||||
assertEquals("OK", expr.getValue(new StandardEvaluationContext(proxy)));
|
assertEquals("OK", expr.getValue(new StandardEvaluationContext(proxy)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompiledExpressionForProxy_SPR16191() {
|
||||||
|
SpelExpressionParser expressionParser =
|
||||||
|
new SpelExpressionParser(new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null));
|
||||||
|
Expression expression = expressionParser.parseExpression("#target.process(#root)");
|
||||||
|
|
||||||
|
VarargsReceiver receiver = new VarargsReceiver();
|
||||||
|
VarargsInterface proxy = (VarargsInterface) Proxy.newProxyInstance(
|
||||||
|
getClass().getClassLoader(), new Class<?>[] {VarargsInterface.class},
|
||||||
|
(proxy1, method, args) -> method.invoke(receiver, args));
|
||||||
|
|
||||||
|
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||||
|
evaluationContext.setVariable("target", proxy);
|
||||||
|
|
||||||
|
String result = expression.getValue(evaluationContext, "foo", String.class);
|
||||||
|
result = expression.getValue(evaluationContext, "foo", String.class);
|
||||||
|
assertEquals("OK", result);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void varargsAndPrimitives_SPR8174() throws Exception {
|
public void varargsAndPrimitives_SPR8174() throws Exception {
|
||||||
EvaluationContext emptyEvalContext = new StandardEvaluationContext();
|
EvaluationContext emptyEvalContext = new StandardEvaluationContext();
|
||||||
|
|||||||
Reference in New Issue
Block a user