47
47
import org .springframework .util .ObjectUtils ;
48
48
49
49
/**
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).
51
52
*
52
53
* @author Andy Clement
53
54
* @author Juergen Hoeller
@@ -101,27 +102,28 @@ protected ValueRef getValueRef(ExpressionState state) throws EvaluationException
101
102
@ Override
102
103
public TypedValue getValueInternal (ExpressionState state ) throws EvaluationException {
103
104
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 ();
106
108
@ Nullable Object [] arguments = getArguments (state );
107
- TypedValue result = getValueInternal (evaluationContext , value , targetType , arguments );
109
+ TypedValue result = getValueInternal (evaluationContext , target , targetType , arguments );
108
110
updateExitTypeDescriptor ();
109
111
return result ;
110
112
}
111
113
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 ) {
114
116
115
117
List <TypeDescriptor > argumentTypes = getArgumentTypes (arguments );
116
- if (value == null ) {
118
+ if (target == null ) {
117
119
throwIfNotNullSafe (argumentTypes );
118
120
return TypedValue .NULL ;
119
121
}
120
122
121
- MethodExecutor executorToUse = getCachedExecutor (evaluationContext , value , targetType , argumentTypes );
123
+ MethodExecutor executorToUse = getCachedExecutor (evaluationContext , target , targetType , argumentTypes );
122
124
if (executorToUse != null ) {
123
125
try {
124
- return executorToUse .execute (evaluationContext , value , arguments );
126
+ return executorToUse .execute (evaluationContext , target , arguments );
125
127
}
126
128
catch (AccessException ex ) {
127
129
// Two reasons this can occur:
@@ -135,7 +137,7 @@ private TypedValue getValueInternal(EvaluationContext evaluationContext,
135
137
// To determine the situation, the AccessException will contain a cause.
136
138
// If the cause is an InvocationTargetException, a user exception was
137
139
// thrown inside the method. Otherwise the method could not be invoked.
138
- throwSimpleExceptionIfPossible (value , ex );
140
+ throwSimpleExceptionIfPossible (target , ex );
139
141
140
142
// At this point we know it wasn't a user problem so worth a retry if a
141
143
// better candidate can be found.
@@ -144,18 +146,18 @@ private TypedValue getValueInternal(EvaluationContext evaluationContext,
144
146
}
145
147
146
148
// either there was no accessor or it no longer existed
147
- executorToUse = findAccessorForMethod (argumentTypes , value , evaluationContext );
149
+ executorToUse = findMethodExecutor (argumentTypes , target , evaluationContext );
148
150
this .cachedExecutor = new CachedMethodExecutor (
149
- executorToUse , (value instanceof Class <?> clazz ? clazz : null ), targetType , argumentTypes );
151
+ executorToUse , (target instanceof Class <?> clazz ? clazz : null ), targetType , argumentTypes );
150
152
try {
151
- return executorToUse .execute (evaluationContext , value , arguments );
153
+ return executorToUse .execute (evaluationContext , target , arguments );
152
154
}
153
155
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 );
156
158
throw new SpelEvaluationException (getStartPosition (), ex ,
157
159
SpelMessage .EXCEPTION_DURING_METHOD_INVOCATION , this .name ,
158
- value .getClass ().getName (), ex .getMessage ());
160
+ target .getClass ().getName (), ex .getMessage ());
159
161
}
160
162
}
161
163
@@ -190,8 +192,8 @@ private List<TypeDescriptor> getArgumentTypes(@Nullable Object... arguments) {
190
192
return Collections .unmodifiableList (descriptors );
191
193
}
192
194
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 ) {
195
197
196
198
List <MethodResolver > methodResolvers = evaluationContext .getMethodResolvers ();
197
199
if (methodResolvers .size () != 1 || !(methodResolvers .get (0 ) instanceof ReflectiveMethodResolver )) {
@@ -200,21 +202,21 @@ private List<TypeDescriptor> getArgumentTypes(@Nullable Object... arguments) {
200
202
}
201
203
202
204
CachedMethodExecutor executorToCheck = this .cachedExecutor ;
203
- if (executorToCheck != null && executorToCheck .isSuitable (value , target , argumentTypes )) {
205
+ if (executorToCheck != null && executorToCheck .isSuitable (target , targetType , argumentTypes )) {
204
206
return executorToCheck .get ();
205
207
}
206
208
this .cachedExecutor = null ;
207
209
return null ;
208
210
}
209
211
210
- private MethodExecutor findAccessorForMethod (List <TypeDescriptor > argumentTypes , Object targetObject ,
212
+ private MethodExecutor findMethodExecutor (List <TypeDescriptor > argumentTypes , Object target ,
211
213
EvaluationContext evaluationContext ) throws SpelEvaluationException {
212
214
213
215
AccessException accessException = null ;
214
216
for (MethodResolver methodResolver : evaluationContext .getMethodResolvers ()) {
215
217
try {
216
218
MethodExecutor methodExecutor = methodResolver .resolve (
217
- evaluationContext , targetObject , this .name , argumentTypes );
219
+ evaluationContext , target , this .name , argumentTypes );
218
220
if (methodExecutor != null ) {
219
221
return methodExecutor ;
220
222
}
@@ -227,7 +229,7 @@ private MethodExecutor findAccessorForMethod(List<TypeDescriptor> argumentTypes,
227
229
228
230
String method = FormatHelper .formatMethodForMessage (this .name , argumentTypes );
229
231
String className = FormatHelper .formatClassNameForMessage (
230
- targetObject instanceof Class <?> clazz ? clazz : targetObject .getClass ());
232
+ target instanceof Class <?> clazz ? clazz : target .getClass ());
231
233
if (accessException != null ) {
232
234
throw new SpelEvaluationException (
233
235
getStartPosition (), accessException , SpelMessage .PROBLEM_LOCATING_METHOD , method , className );
@@ -241,15 +243,15 @@ private MethodExecutor findAccessorForMethod(List<TypeDescriptor> argumentTypes,
241
243
* Decode the AccessException, throwing a lightweight evaluation exception or,
242
244
* if the cause was a RuntimeException, throw the RuntimeException directly.
243
245
*/
244
- private void throwSimpleExceptionIfPossible (Object value , AccessException ex ) {
246
+ private void throwSimpleExceptionIfPossible (Object target , AccessException ex ) {
245
247
if (ex .getCause () instanceof InvocationTargetException cause ) {
246
248
Throwable rootCause = cause .getCause ();
247
249
if (rootCause instanceof RuntimeException runtimeException ) {
248
250
throw runtimeException ;
249
251
}
250
252
throw new ExpressionInvocationTargetException (getStartPosition (),
251
253
"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 );
253
255
}
254
256
}
255
257
@@ -376,23 +378,23 @@ private class MethodValueRef implements ValueRef {
376
378
377
379
private final EvaluationContext evaluationContext ;
378
380
379
- private final @ Nullable Object value ;
381
+ private final @ Nullable Object target ;
380
382
381
383
private final @ Nullable TypeDescriptor targetType ;
382
384
383
385
private final @ Nullable Object [] arguments ;
384
386
385
387
public MethodValueRef (ExpressionState state , @ Nullable Object [] arguments ) {
386
388
this .evaluationContext = state .getEvaluationContext ();
387
- this .value = state .getActiveContextObject ().getValue ();
389
+ this .target = state .getActiveContextObject ().getValue ();
388
390
this .targetType = state .getActiveContextObject ().getTypeDescriptor ();
389
391
this .arguments = arguments ;
390
392
}
391
393
392
394
@ Override
393
395
public TypedValue getValue () {
394
396
TypedValue result = MethodReference .this .getValueInternal (
395
- this .evaluationContext , this .value , this .targetType , this .arguments );
397
+ this .evaluationContext , this .target , this .targetType , this .arguments );
396
398
updateExitTypeDescriptor ();
397
399
return result ;
398
400
}
@@ -409,32 +411,16 @@ public boolean isWritable() {
409
411
}
410
412
411
413
412
- private static class CachedMethodExecutor {
414
+ private record CachedMethodExecutor (MethodExecutor methodExecutor , @ Nullable Class <?> staticClass ,
415
+ @ Nullable TypeDescriptor targetType , List <TypeDescriptor > argumentTypes ) {
413
416
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 ));
434
420
}
435
421
436
422
public boolean hasProxyTarget () {
437
- return (this .target != null && Proxy .isProxyClass (this .target .getType ()));
423
+ return (this .targetType != null && Proxy .isProxyClass (this .targetType .getType ()));
438
424
}
439
425
440
426
public MethodExecutor get () {
0 commit comments