@@ -76,19 +76,19 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
7676		Object  value  = state .getActiveContextObject ().getValue ();
7777		TypeDescriptor  targetType  = state .getActiveContextObject ().getTypeDescriptor ();
7878		Object [] arguments  = getArguments (state );
79- 		return  getValueInternal (evaluationContext , value , arguments ,  targetType );
79+ 		return  getValueInternal (evaluationContext , value , targetType ,  arguments );
8080	}
8181
8282	private  TypedValue  getValueInternal (EvaluationContext  evaluationContext ,
83- 			Object  value , Object [] arguments ,  TypeDescriptor   targetType ) {
83+ 			Object  value , TypeDescriptor   targetType ,  Object [] arguments ) {
8484
8585		List <TypeDescriptor > argumentTypes  = getArgumentTypes (arguments );
8686		if  (value  == null ) {
8787			throwIfNotNullSafe (argumentTypes );
8888			return  TypedValue .NULL ;
8989		}
9090
91- 		MethodExecutor  executorToUse  = getCachedExecutor (targetType , argumentTypes );
91+ 		MethodExecutor  executorToUse  = getCachedExecutor (value ,  targetType , argumentTypes );
9292		if  (executorToUse  != null ) {
9393			try  {
9494				return  executorToUse .execute (evaluationContext , value , arguments );
@@ -108,15 +108,16 @@ private TypedValue getValueInternal(EvaluationContext evaluationContext,
108108				// Otherwise the method could not be invoked. 
109109				throwSimpleExceptionIfPossible (value , ae );
110110
111- 				// at  this point we know it wasn't a user problem so worth a retry if a 
111+ 				// At  this point we know it wasn't a user problem so worth a retry if a 
112112				// better candidate can be found 
113113				this .cachedExecutor  = null ;
114114			}
115115		}
116116
117117		// either there was no accessor or it no longer existed 
118118		executorToUse  = findAccessorForMethod (this .name , argumentTypes , value , evaluationContext );
119- 		this .cachedExecutor  = new  CachedMethodExecutor (executorToUse , targetType , argumentTypes );
119+ 		this .cachedExecutor  = new  CachedMethodExecutor (
120+ 				executorToUse , (value  instanceof  Class  ? (Class <?>) value  : null ), targetType , argumentTypes );
120121		try  {
121122			return  executorToUse .execute (evaluationContext , value , arguments );
122123		}
@@ -140,8 +141,7 @@ private void throwIfNotNullSafe(List<TypeDescriptor> argumentTypes) {
140141	private  Object [] getArguments (ExpressionState  state ) {
141142		Object [] arguments  = new  Object [getChildCount ()];
142143		for  (int  i  = 0 ; i  < arguments .length ; i ++) {
143- 			// Make the root object the active context again for evaluating the parameter 
144- 			// expressions 
144+ 			// Make the root object the active context again for evaluating the parameter expressions 
145145			try  {
146146				state .pushActiveContextObject (state .getRootContextObject ());
147147				arguments [i ] = this .children [i ].getValueInternal (state ).getValue ();
@@ -161,40 +161,39 @@ private List<TypeDescriptor> getArgumentTypes(Object... arguments) {
161161		return  Collections .unmodifiableList (descriptors );
162162	}
163163
164- 	private  MethodExecutor  getCachedExecutor (TypeDescriptor  target , List <TypeDescriptor > argumentTypes ) {
164+ 	private  MethodExecutor  getCachedExecutor (Object   value ,  TypeDescriptor  target , List <TypeDescriptor > argumentTypes ) {
165165		CachedMethodExecutor  executorToCheck  = this .cachedExecutor ;
166- 		if  (executorToCheck  != null  && executorToCheck .isSuitable (target , argumentTypes )) {
166+ 		if  (executorToCheck  != null  && executorToCheck .isSuitable (value ,  target , argumentTypes )) {
167167			return  executorToCheck .get ();
168168		}
169169		this .cachedExecutor  = null ;
170170		return  null ;
171171	}
172172
173- 	private  MethodExecutor  findAccessorForMethod (String  name ,
174- 			List <TypeDescriptor > argumentTypes , Object  contextObject ,
175- 			EvaluationContext  evaluationContext ) throws  SpelEvaluationException  {
173+ 	private  MethodExecutor  findAccessorForMethod (String  name , List <TypeDescriptor > argumentTypes ,
174+ 			Object  targetObject , EvaluationContext  evaluationContext ) throws  SpelEvaluationException  {
176175
177176		List <MethodResolver > methodResolvers  = evaluationContext .getMethodResolvers ();
178177		if  (methodResolvers  != null ) {
179178			for  (MethodResolver  methodResolver  : methodResolvers ) {
180179				try  {
181180					MethodExecutor  methodExecutor  = methodResolver .resolve (
182- 							evaluationContext , contextObject , name , argumentTypes );
181+ 							evaluationContext , targetObject , name , argumentTypes );
183182					if  (methodExecutor  != null ) {
184183						return  methodExecutor ;
185184					}
186185				}
187186				catch  (AccessException  ex ) {
188187					throw  new  SpelEvaluationException (getStartPosition (), ex ,
189- 							SpelMessage .PROBLEM_LOCATING_METHOD , name , contextObject .getClass ());
188+ 							SpelMessage .PROBLEM_LOCATING_METHOD , name , targetObject .getClass ());
190189				}
191190			}
192191		}
193192
194193		throw  new  SpelEvaluationException (getStartPosition (), SpelMessage .METHOD_NOT_FOUND ,
195194				FormatHelper .formatMethodForMessage (name , argumentTypes ),
196195				FormatHelper .formatClassNameForMessage (
197- 						contextObject  instanceof  Class  ? ((Class <?>) contextObject ) : contextObject .getClass ()));
196+ 						targetObject  instanceof  Class  ? ((Class <?>) targetObject ) : targetObject .getClass ()));
198197	}
199198
200199	/** 
@@ -249,7 +248,7 @@ public MethodValueRef(ExpressionState state) {
249248
250249		@ Override 
251250		public  TypedValue  getValue () {
252- 			return  getValueInternal (this .evaluationContext , this .value , this .arguments , this .targetType );
251+ 			return  getValueInternal (this .evaluationContext , this .value , this .targetType , this .arguments );
253252		}
254253
255254		@ Override 
@@ -268,18 +267,22 @@ private static class CachedMethodExecutor {
268267
269268		private  final  MethodExecutor  methodExecutor ;
270269
270+ 		private  final  Class <?> staticClass ;
271+ 
271272		private  final  TypeDescriptor  target ;
272273
273274		private  final  List <TypeDescriptor > argumentTypes ;
274275
275- 		public  CachedMethodExecutor (MethodExecutor  methodExecutor , TypeDescriptor  target , List <TypeDescriptor > argumentTypes ) {
276+ 		public  CachedMethodExecutor (MethodExecutor  methodExecutor , Class <?> staticClass ,
277+ 				TypeDescriptor  target , List <TypeDescriptor > argumentTypes ) {
276278			this .methodExecutor  = methodExecutor ;
279+ 			this .staticClass  = staticClass ;
277280			this .target  = target ;
278281			this .argumentTypes  = argumentTypes ;
279282		}
280283
281- 		public  boolean  isSuitable (TypeDescriptor  target , List <TypeDescriptor > argumentTypes ) {
282- 			return  (this .methodExecutor  !=  null  &&  this .target  !=  null  &&
284+ 		public  boolean  isSuitable (Object   value ,  TypeDescriptor  target , List <TypeDescriptor > argumentTypes ) {
285+ 			return  (( this .staticClass  ==  null  ||  this .staticClass . equals ( value ))  &&
283286					this .target .equals (target ) && this .argumentTypes .equals (argumentTypes ));
284287		}
285288
0 commit comments