Browse Source

MethodReference treats proxy-targeting expressions as non-compilable

Issue: SPR-16191
pull/1592/merge
Juergen Hoeller 8 years ago
parent
commit
c30145d6f9
  1. 11
      spring-expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java
  2. 19
      spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java

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

@ -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;
} }

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

@ -731,6 +731,25 @@ public class SpelReproTests extends AbstractExpressionTests {
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();

Loading…
Cancel
Save