Fix double SPeL evaluation of parameter

When a node of an SPeL expression was a call to a bean referenced
 in a method argument, the expression was resolved twice.

 The resolved arguments are now specified to MethodValueRef instead
 of resolving the arguments again in the constructor

 Issue: SPR-11445
This commit is contained in:
Stephane Nicoll 2014-03-06 14:44:13 +01:00
parent c8f2e07182
commit 519799e1cf
2 changed files with 37 additions and 3 deletions

View File

@ -68,7 +68,7 @@ public class MethodReference extends SpelNodeImpl {
throwIfNotNullSafe(getArgumentTypes(arguments)); throwIfNotNullSafe(getArgumentTypes(arguments));
return ValueRef.NullValueRef.instance; return ValueRef.NullValueRef.instance;
} }
return new MethodValueRef(state); return new MethodValueRef(state, arguments);
} }
@Override @Override
@ -246,11 +246,11 @@ public class MethodReference extends SpelNodeImpl {
private final Object[] arguments; private final Object[] arguments;
public MethodValueRef(ExpressionState state) { public MethodValueRef(ExpressionState state, Object[] arguments) {
this.evaluationContext = state.getEvaluationContext(); this.evaluationContext = state.getEvaluationContext();
this.value = state.getActiveContextObject().getValue(); this.value = state.getActiveContextObject().getValue();
this.targetType = state.getActiveContextObject().getTypeDescriptor(); this.targetType = state.getActiveContextObject().getTypeDescriptor();
this.arguments = getArguments(state); this.arguments = arguments;
} }
@Override @Override

View File

@ -29,6 +29,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -1825,6 +1826,39 @@ public class SpelReproTests extends AbstractExpressionTests {
assertEquals("two", list.get(1)); assertEquals("two", list.get(1));
} }
@Test
public void SPR11445_simple() {
StandardEvaluationContext context = new StandardEvaluationContext(new Spr11445Class());
Expression expr = new SpelExpressionParser().parseRaw("echo(parameter())");
assertEquals(1, expr.getValue(context));
}
@Test
public void SPR11445_beanReference() {
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new Spr11445Class());
Expression expr = new SpelExpressionParser().parseRaw("@bean.echo(@bean.parameter())");
assertEquals(1, expr.getValue(context));
}
static class Spr11445Class implements BeanResolver {
private final AtomicInteger counter = new AtomicInteger();
public int echo(int invocation) {
return invocation;
}
public int parameter() {
return counter.incrementAndGet();
}
@Override
public Object resolve(EvaluationContext context, String beanName) throws AccessException {
return beanName.equals("bean") ? this : null;
}
}
@Test @Test
public void SPR11494() { public void SPR11494() {
Expression exp = new SpelExpressionParser().parseExpression("T(java.util.Arrays).asList('a','b')"); Expression exp = new SpelExpressionParser().parseExpression("T(java.util.Arrays).asList('a','b')");