@@ -48,14 +48,12 @@ public class MethodReference extends SpelNodeImpl {
48
48
49
49
private volatile CachedMethodExecutor cachedExecutor ;
50
50
51
-
52
51
public MethodReference (boolean nullSafe , String methodName , int pos , SpelNodeImpl ... arguments ) {
53
52
super (pos , arguments );
54
53
this .name = methodName ;
55
54
this .nullSafe = nullSafe ;
56
55
}
57
56
58
-
59
57
public final String getName () {
60
58
return this .name ;
61
59
}
@@ -102,6 +100,9 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
102
100
state .popActiveContextObject ();
103
101
}
104
102
}
103
+ TypedValue activeContextObject = state .getActiveContextObject ();
104
+ TypeDescriptor target = (activeContextObject == null ? null
105
+ : activeContextObject .getTypeDescriptor ());
105
106
List <TypeDescriptor > argumentTypes = getTypes (arguments );
106
107
if (currentContext .getValue () == null ) {
107
108
if (this .nullSafe ) {
@@ -113,7 +114,7 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
113
114
}
114
115
}
115
116
116
- MethodExecutor executorToUse = getCachedExecutor (argumentTypes );
117
+ MethodExecutor executorToUse = getCachedExecutor (target , argumentTypes );
117
118
if (executorToUse != null ) {
118
119
try {
119
120
return executorToUse .execute (state .getEvaluationContext (),
@@ -139,7 +140,7 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
139
140
140
141
// either there was no accessor or it no longer existed
141
142
executorToUse = findAccessorForMethod (this .name , argumentTypes , state );
142
- this .cachedExecutor = new CachedMethodExecutor (executorToUse , argumentTypes );
143
+ this .cachedExecutor = new CachedMethodExecutor (executorToUse , target , argumentTypes );
143
144
try {
144
145
return executorToUse .execute (state .getEvaluationContext (),
145
146
state .getActiveContextObject ().getValue (), arguments );
@@ -227,15 +228,15 @@ private MethodExecutor findAccessorForMethod(String name,
227
228
: contextObject .getClass ()));
228
229
}
229
230
230
- private MethodExecutor getCachedExecutor (List <TypeDescriptor > argumentTypes ) {
231
- if (this .cachedExecutor == null || !this .cachedExecutor .isSuitable (argumentTypes )) {
231
+ private MethodExecutor getCachedExecutor (TypeDescriptor target ,
232
+ List <TypeDescriptor > argumentTypes ) {
233
+ if (this .cachedExecutor == null || !this .cachedExecutor .isSuitable (target , argumentTypes )) {
232
234
this .cachedExecutor = null ;
233
235
return null ;
234
236
}
235
237
return this .cachedExecutor .get ();
236
238
}
237
239
238
-
239
240
private class MethodValueRef implements ValueRef {
240
241
241
242
private final ExpressionState state ;
@@ -244,23 +245,28 @@ private class MethodValueRef implements ValueRef {
244
245
245
246
private final Object target ;
246
247
248
+ private TypeDescriptor targetType ;
249
+
247
250
private final Object [] arguments ;
248
251
249
252
private List <TypeDescriptor > argumentTypes ;
250
253
251
254
252
- MethodValueRef (ExpressionState state , EvaluationContext evaluationContext , Object object , Object [] arguments ) {
255
+ MethodValueRef (ExpressionState state , EvaluationContext evaluationContext ,
256
+ Object object , Object [] arguments ) {
253
257
this .state = state ;
254
258
this .evaluationContext = evaluationContext ;
255
259
this .target = object ;
260
+ this .targetType = TypeDescriptor .valueOf (target .getClass ());
256
261
this .arguments = arguments ;
257
262
this .argumentTypes = getTypes (this .arguments );
258
263
}
259
264
260
265
261
266
@ Override
262
267
public TypedValue getValue () {
263
- MethodExecutor executorToUse = getCachedExecutor (this .argumentTypes );
268
+ MethodExecutor executorToUse = getCachedExecutor (this .targetType ,
269
+ this .argumentTypes );
264
270
if (executorToUse != null ) {
265
271
try {
266
272
return executorToUse .execute (this .evaluationContext , this .target , this .arguments );
@@ -285,7 +291,7 @@ public TypedValue getValue() {
285
291
286
292
// either there was no accessor or it no longer existed
287
293
executorToUse = findAccessorForMethod (MethodReference .this .name , argumentTypes , this .target , this .evaluationContext );
288
- MethodReference .this .cachedExecutor = new CachedMethodExecutor (executorToUse , this .argumentTypes );
294
+ MethodReference .this .cachedExecutor = new CachedMethodExecutor (executorToUse , this .targetType , this . argumentTypes );
289
295
try {
290
296
return executorToUse .execute (this .evaluationContext , this .target , this .arguments );
291
297
}
@@ -310,23 +316,24 @@ public boolean isWritable() {
310
316
}
311
317
}
312
318
313
-
314
319
private static class CachedMethodExecutor {
315
320
316
321
private final MethodExecutor methodExecutor ;
317
322
318
- private final List < TypeDescriptor > argumentTypes ;
323
+ private final TypeDescriptor target ;
319
324
325
+ private final List <TypeDescriptor > argumentTypes ;
320
326
321
- public CachedMethodExecutor (MethodExecutor methodExecutor ,
327
+ public CachedMethodExecutor (MethodExecutor methodExecutor , TypeDescriptor target ,
322
328
List <TypeDescriptor > argumentTypes ) {
323
329
this .methodExecutor = methodExecutor ;
330
+ this .target = target ;
324
331
this .argumentTypes = argumentTypes ;
325
332
}
326
333
327
-
328
- public boolean isSuitable ( List < TypeDescriptor > argumentTypes ) {
329
- return ( this .methodExecutor != null && this .argumentTypes .equals (argumentTypes ));
334
+ public boolean isSuitable ( TypeDescriptor target , List < TypeDescriptor > argumentTypes ) {
335
+ return ( this . methodExecutor != null && this . target != null
336
+ && this .target . equals ( target ) && this .argumentTypes .equals (argumentTypes ));
330
337
}
331
338
332
339
public MethodExecutor get () {
0 commit comments