|
|
|
@ -32,6 +32,7 @@ import org.springframework.expression.TypedValue; |
|
|
|
import org.springframework.expression.spel.ExpressionState; |
|
|
|
import org.springframework.expression.spel.ExpressionState; |
|
|
|
import org.springframework.expression.spel.SpelEvaluationException; |
|
|
|
import org.springframework.expression.spel.SpelEvaluationException; |
|
|
|
import org.springframework.expression.spel.SpelMessage; |
|
|
|
import org.springframework.expression.spel.SpelMessage; |
|
|
|
|
|
|
|
import org.springframework.expression.spel.support.ReflectiveMethodResolver; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Expression language AST node that represents a method reference. |
|
|
|
* Expression language AST node that represents a method reference. |
|
|
|
@ -88,7 +89,7 @@ public class MethodReference extends SpelNodeImpl { |
|
|
|
return TypedValue.NULL; |
|
|
|
return TypedValue.NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
MethodExecutor executorToUse = getCachedExecutor(value, targetType, argumentTypes); |
|
|
|
MethodExecutor executorToUse = getCachedExecutor(evaluationContext, value, targetType, argumentTypes); |
|
|
|
if (executorToUse != null) { |
|
|
|
if (executorToUse != null) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
return executorToUse.execute(evaluationContext, value, arguments); |
|
|
|
return executorToUse.execute(evaluationContext, value, arguments); |
|
|
|
@ -104,8 +105,7 @@ public class MethodReference extends SpelNodeImpl { |
|
|
|
|
|
|
|
|
|
|
|
// To determine the situation, the AccessException will contain a cause.
|
|
|
|
// To determine the situation, the AccessException will contain a cause.
|
|
|
|
// If the cause is an InvocationTargetException, a user exception was
|
|
|
|
// If the cause is an InvocationTargetException, a user exception was
|
|
|
|
// thrown inside the method.
|
|
|
|
// thrown inside the method. Otherwise the method could not be invoked.
|
|
|
|
// Otherwise the method could not be invoked.
|
|
|
|
|
|
|
|
throwSimpleExceptionIfPossible(value, ae); |
|
|
|
throwSimpleExceptionIfPossible(value, ae); |
|
|
|
|
|
|
|
|
|
|
|
// At this point we know it wasn't a user problem so worth a retry if a
|
|
|
|
// At this point we know it wasn't a user problem so worth a retry if a
|
|
|
|
@ -161,7 +161,16 @@ public class MethodReference extends SpelNodeImpl { |
|
|
|
return Collections.unmodifiableList(descriptors); |
|
|
|
return Collections.unmodifiableList(descriptors); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private MethodExecutor getCachedExecutor(Object value, TypeDescriptor target, List<TypeDescriptor> argumentTypes) { |
|
|
|
private MethodExecutor getCachedExecutor(EvaluationContext evaluationContext, Object value, |
|
|
|
|
|
|
|
TypeDescriptor target, List<TypeDescriptor> argumentTypes) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<MethodResolver> methodResolvers = evaluationContext.getMethodResolvers(); |
|
|
|
|
|
|
|
if (methodResolvers == null || methodResolvers.size() != 1 || |
|
|
|
|
|
|
|
!(methodResolvers.get(0) instanceof ReflectiveMethodResolver)) { |
|
|
|
|
|
|
|
// Not a default ReflectiveMethodResolver - don't know whether caching is valid
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CachedMethodExecutor executorToCheck = this.cachedExecutor; |
|
|
|
CachedMethodExecutor executorToCheck = this.cachedExecutor; |
|
|
|
if (executorToCheck != null && executorToCheck.isSuitable(value, target, argumentTypes)) { |
|
|
|
if (executorToCheck != null && executorToCheck.isSuitable(value, target, argumentTypes)) { |
|
|
|
return executorToCheck.get(); |
|
|
|
return executorToCheck.get(); |
|
|
|
|