4747import org .springframework .util .ObjectUtils ;
4848
4949/**
50- * Expression language AST node that represents a method reference.
50+ * Expression language AST node that represents a method reference (i.e., a
51+ * method invocation other than a simple property reference).
5152 *
5253 * @author Andy Clement
5354 * @author Juergen Hoeller
@@ -101,27 +102,28 @@ protected ValueRef getValueRef(ExpressionState state) throws EvaluationException
101102 @ Override
102103 public TypedValue getValueInternal (ExpressionState state ) throws EvaluationException {
103104 EvaluationContext evaluationContext = state .getEvaluationContext ();
104- Object value = state .getActiveContextObject ().getValue ();
105- TypeDescriptor targetType = state .getActiveContextObject ().getTypeDescriptor ();
105+ TypedValue contextObject = state .getActiveContextObject ();
106+ Object target = contextObject .getValue ();
107+ TypeDescriptor targetType = contextObject .getTypeDescriptor ();
106108 @ Nullable Object [] arguments = getArguments (state );
107- TypedValue result = getValueInternal (evaluationContext , value , targetType , arguments );
109+ TypedValue result = getValueInternal (evaluationContext , target , targetType , arguments );
108110 updateExitTypeDescriptor ();
109111 return result ;
110112 }
111113
112- private TypedValue getValueInternal (EvaluationContext evaluationContext ,
113- @ Nullable Object value , @ Nullable TypeDescriptor targetType , @ Nullable Object [] arguments ) {
114+ private TypedValue getValueInternal (EvaluationContext evaluationContext , @ Nullable Object target ,
115+ @ Nullable TypeDescriptor targetType , @ Nullable Object [] arguments ) {
114116
115117 List <TypeDescriptor > argumentTypes = getArgumentTypes (arguments );
116- if (value == null ) {
118+ if (target == null ) {
117119 throwIfNotNullSafe (argumentTypes );
118120 return TypedValue .NULL ;
119121 }
120122
121- MethodExecutor executorToUse = getCachedExecutor (evaluationContext , value , targetType , argumentTypes );
123+ MethodExecutor executorToUse = getCachedExecutor (evaluationContext , target , targetType , argumentTypes );
122124 if (executorToUse != null ) {
123125 try {
124- return executorToUse .execute (evaluationContext , value , arguments );
126+ return executorToUse .execute (evaluationContext , target , arguments );
125127 }
126128 catch (AccessException ex ) {
127129 // Two reasons this can occur:
@@ -135,7 +137,7 @@ private TypedValue getValueInternal(EvaluationContext evaluationContext,
135137 // To determine the situation, the AccessException will contain a cause.
136138 // If the cause is an InvocationTargetException, a user exception was
137139 // thrown inside the method. Otherwise the method could not be invoked.
138- throwSimpleExceptionIfPossible (value , ex );
140+ throwSimpleExceptionIfPossible (target , ex );
139141
140142 // At this point we know it wasn't a user problem so worth a retry if a
141143 // better candidate can be found.
@@ -144,18 +146,18 @@ private TypedValue getValueInternal(EvaluationContext evaluationContext,
144146 }
145147
146148 // either there was no accessor or it no longer existed
147- executorToUse = findAccessorForMethod (argumentTypes , value , evaluationContext );
149+ executorToUse = findMethodExecutor (argumentTypes , target , evaluationContext );
148150 this .cachedExecutor = new CachedMethodExecutor (
149- executorToUse , (value instanceof Class <?> clazz ? clazz : null ), targetType , argumentTypes );
151+ executorToUse , (target instanceof Class <?> clazz ? clazz : null ), targetType , argumentTypes );
150152 try {
151- return executorToUse .execute (evaluationContext , value , arguments );
153+ return executorToUse .execute (evaluationContext , target , arguments );
152154 }
153155 catch (AccessException ex ) {
154- // Same unwrapping exception handling as above in above catch block
155- throwSimpleExceptionIfPossible (value , ex );
156+ // Same unwrapping exception handling as in above catch block
157+ throwSimpleExceptionIfPossible (target , ex );
156158 throw new SpelEvaluationException (getStartPosition (), ex ,
157159 SpelMessage .EXCEPTION_DURING_METHOD_INVOCATION , this .name ,
158- value .getClass ().getName (), ex .getMessage ());
160+ target .getClass ().getName (), ex .getMessage ());
159161 }
160162 }
161163
@@ -190,8 +192,8 @@ private List<TypeDescriptor> getArgumentTypes(@Nullable Object... arguments) {
190192 return Collections .unmodifiableList (descriptors );
191193 }
192194
193- private @ Nullable MethodExecutor getCachedExecutor (EvaluationContext evaluationContext , Object value ,
194- @ Nullable TypeDescriptor target , List <TypeDescriptor > argumentTypes ) {
195+ private @ Nullable MethodExecutor getCachedExecutor (EvaluationContext evaluationContext , Object target ,
196+ @ Nullable TypeDescriptor targetType , List <TypeDescriptor > argumentTypes ) {
195197
196198 List <MethodResolver > methodResolvers = evaluationContext .getMethodResolvers ();
197199 if (methodResolvers .size () != 1 || !(methodResolvers .get (0 ) instanceof ReflectiveMethodResolver )) {
@@ -200,21 +202,21 @@ private List<TypeDescriptor> getArgumentTypes(@Nullable Object... arguments) {
200202 }
201203
202204 CachedMethodExecutor executorToCheck = this .cachedExecutor ;
203- if (executorToCheck != null && executorToCheck .isSuitable (value , target , argumentTypes )) {
205+ if (executorToCheck != null && executorToCheck .isSuitable (target , targetType , argumentTypes )) {
204206 return executorToCheck .get ();
205207 }
206208 this .cachedExecutor = null ;
207209 return null ;
208210 }
209211
210- private MethodExecutor findAccessorForMethod (List <TypeDescriptor > argumentTypes , Object targetObject ,
212+ private MethodExecutor findMethodExecutor (List <TypeDescriptor > argumentTypes , Object target ,
211213 EvaluationContext evaluationContext ) throws SpelEvaluationException {
212214
213215 AccessException accessException = null ;
214216 for (MethodResolver methodResolver : evaluationContext .getMethodResolvers ()) {
215217 try {
216218 MethodExecutor methodExecutor = methodResolver .resolve (
217- evaluationContext , targetObject , this .name , argumentTypes );
219+ evaluationContext , target , this .name , argumentTypes );
218220 if (methodExecutor != null ) {
219221 return methodExecutor ;
220222 }
@@ -227,7 +229,7 @@ private MethodExecutor findAccessorForMethod(List<TypeDescriptor> argumentTypes,
227229
228230 String method = FormatHelper .formatMethodForMessage (this .name , argumentTypes );
229231 String className = FormatHelper .formatClassNameForMessage (
230- targetObject instanceof Class <?> clazz ? clazz : targetObject .getClass ());
232+ target instanceof Class <?> clazz ? clazz : target .getClass ());
231233 if (accessException != null ) {
232234 throw new SpelEvaluationException (
233235 getStartPosition (), accessException , SpelMessage .PROBLEM_LOCATING_METHOD , method , className );
@@ -241,15 +243,15 @@ private MethodExecutor findAccessorForMethod(List<TypeDescriptor> argumentTypes,
241243 * Decode the AccessException, throwing a lightweight evaluation exception or,
242244 * if the cause was a RuntimeException, throw the RuntimeException directly.
243245 */
244- private void throwSimpleExceptionIfPossible (Object value , AccessException ex ) {
246+ private void throwSimpleExceptionIfPossible (Object target , AccessException ex ) {
245247 if (ex .getCause () instanceof InvocationTargetException cause ) {
246248 Throwable rootCause = cause .getCause ();
247249 if (rootCause instanceof RuntimeException runtimeException ) {
248250 throw runtimeException ;
249251 }
250252 throw new ExpressionInvocationTargetException (getStartPosition (),
251253 "A problem occurred when trying to execute method '" + this .name +
252- "' on object of type [" + value .getClass ().getName () + "]" , rootCause );
254+ "' on object of type [" + target .getClass ().getName () + "]" , rootCause );
253255 }
254256 }
255257
@@ -376,23 +378,23 @@ private class MethodValueRef implements ValueRef {
376378
377379 private final EvaluationContext evaluationContext ;
378380
379- private final @ Nullable Object value ;
381+ private final @ Nullable Object target ;
380382
381383 private final @ Nullable TypeDescriptor targetType ;
382384
383385 private final @ Nullable Object [] arguments ;
384386
385387 public MethodValueRef (ExpressionState state , @ Nullable Object [] arguments ) {
386388 this .evaluationContext = state .getEvaluationContext ();
387- this .value = state .getActiveContextObject ().getValue ();
389+ this .target = state .getActiveContextObject ().getValue ();
388390 this .targetType = state .getActiveContextObject ().getTypeDescriptor ();
389391 this .arguments = arguments ;
390392 }
391393
392394 @ Override
393395 public TypedValue getValue () {
394396 TypedValue result = MethodReference .this .getValueInternal (
395- this .evaluationContext , this .value , this .targetType , this .arguments );
397+ this .evaluationContext , this .target , this .targetType , this .arguments );
396398 updateExitTypeDescriptor ();
397399 return result ;
398400 }
@@ -409,32 +411,16 @@ public boolean isWritable() {
409411 }
410412
411413
412- private static class CachedMethodExecutor {
414+ private record CachedMethodExecutor (MethodExecutor methodExecutor , @ Nullable Class <?> staticClass ,
415+ @ Nullable TypeDescriptor targetType , List <TypeDescriptor > argumentTypes ) {
413416
414- private final MethodExecutor methodExecutor ;
415-
416- private final @ Nullable Class <?> staticClass ;
417-
418- private final @ Nullable TypeDescriptor target ;
419-
420- private final List <TypeDescriptor > argumentTypes ;
421-
422- public CachedMethodExecutor (MethodExecutor methodExecutor , @ Nullable Class <?> staticClass ,
423- @ Nullable TypeDescriptor target , List <TypeDescriptor > argumentTypes ) {
424-
425- this .methodExecutor = methodExecutor ;
426- this .staticClass = staticClass ;
427- this .target = target ;
428- this .argumentTypes = argumentTypes ;
429- }
430-
431- public boolean isSuitable (Object value , @ Nullable TypeDescriptor target , List <TypeDescriptor > argumentTypes ) {
432- return ((this .staticClass == null || this .staticClass == value ) &&
433- ObjectUtils .nullSafeEquals (this .target , target ) && this .argumentTypes .equals (argumentTypes ));
417+ public boolean isSuitable (Object target , @ Nullable TypeDescriptor targetType , List <TypeDescriptor > argumentTypes ) {
418+ return ((this .staticClass == null || this .staticClass == target ) &&
419+ ObjectUtils .nullSafeEquals (this .targetType , targetType ) && this .argumentTypes .equals (argumentTypes ));
434420 }
435421
436422 public boolean hasProxyTarget () {
437- return (this .target != null && Proxy .isProxyClass (this .target .getType ()));
423+ return (this .targetType != null && Proxy .isProxyClass (this .targetType .getType ()));
438424 }
439425
440426 public MethodExecutor get () {
0 commit comments