31
31
import java .util .Comparator ;
32
32
import java .util .Set ;
33
33
34
+ import org .springframework .beans .BeanMetadataElement ;
34
35
import org .springframework .beans .factory .ObjectFactory ;
36
+ import org .springframework .beans .factory .config .TypedStringValue ;
35
37
import org .springframework .util .Assert ;
36
38
import org .springframework .util .ClassUtils ;
37
39
@@ -192,8 +194,8 @@ public static Class<?> resolveReturnTypeForFactoryMethod(Method method, Object[]
192
194
193
195
TypeVariable <Method >[] declaredTypeVariables = method .getTypeParameters ();
194
196
Type genericReturnType = method .getGenericReturnType ();
195
- Type [] methodArgumentTypes = method .getGenericParameterTypes ();
196
- Assert .isTrue (args .length == methodArgumentTypes .length , "Argument array does not match parameter count" );
197
+ Type [] methodParameterTypes = method .getGenericParameterTypes ();
198
+ Assert .isTrue (args .length == methodParameterTypes .length , "Argument array does not match parameter count" );
197
199
198
200
// Ensure that the type variable (e.g., T) is declared directly on the method
199
201
// itself (e.g., via <T>), not on the enclosing class or interface.
@@ -206,30 +208,57 @@ public static Class<?> resolveReturnTypeForFactoryMethod(Method method, Object[]
206
208
}
207
209
208
210
if (locallyDeclaredTypeVariableMatchesReturnType ) {
209
- for (int i = 0 ; i < methodArgumentTypes .length ; i ++) {
210
- Type currentMethodArgumentType = methodArgumentTypes [i ];
211
- if (currentMethodArgumentType .equals (genericReturnType )) {
212
- return args [i ].getClass ();
211
+ for (int i = 0 ; i < methodParameterTypes .length ; i ++) {
212
+ Type methodParameterType = methodParameterTypes [i ];
213
+ Object arg = args [i ];
214
+ if (methodParameterType .equals (genericReturnType )) {
215
+ if (arg instanceof TypedStringValue ) {
216
+ TypedStringValue typedValue = ((TypedStringValue ) arg );
217
+ if (typedValue .hasTargetType ()) {
218
+ return typedValue .getTargetType ();
219
+ }
220
+ try {
221
+ return typedValue .resolveTargetType (classLoader );
222
+ }
223
+ catch (ClassNotFoundException ex ) {
224
+ throw new IllegalStateException ("Failed to resolve typed value" , ex );
225
+ }
226
+ }
227
+ // Only consider argument type if it is a simple value...
228
+ if (arg != null && !(arg instanceof BeanMetadataElement )) {
229
+ return arg .getClass ();
230
+ }
231
+ return method .getReturnType ();
213
232
}
214
- if (currentMethodArgumentType instanceof ParameterizedType ) {
215
- ParameterizedType parameterizedType = (ParameterizedType ) currentMethodArgumentType ;
233
+ else if (methodParameterType instanceof ParameterizedType ) {
234
+ ParameterizedType parameterizedType = (ParameterizedType ) methodParameterType ;
216
235
Type [] actualTypeArguments = parameterizedType .getActualTypeArguments ();
217
236
for (Type typeArg : actualTypeArguments ) {
218
237
if (typeArg .equals (genericReturnType )) {
219
- Object arg = args [i ];
220
238
if (arg instanceof Class ) {
221
239
return (Class <?>) arg ;
222
240
}
223
- else if (arg instanceof String ) {
224
- try {
225
- return classLoader .loadClass ((String ) arg );
241
+ else {
242
+ String className = null ;
243
+ if (arg instanceof String ) {
244
+ className = (String ) arg ;
226
245
}
227
- catch (ClassNotFoundException ex ) {
228
- throw new IllegalStateException (
229
- "Could not resolve specified class name argument [" + arg + "]" , ex );
246
+ else if (arg instanceof TypedStringValue ) {
247
+ TypedStringValue typedValue = ((TypedStringValue ) arg );
248
+ String targetTypeName = typedValue .getTargetTypeName ();
249
+ if (targetTypeName == null || Class .class .getName ().equals (targetTypeName )) {
250
+ className = typedValue .getValue ();
251
+ }
252
+ }
253
+ if (className != null ) {
254
+ try {
255
+ return classLoader .loadClass (className );
256
+ }
257
+ catch (ClassNotFoundException ex ) {
258
+ throw new IllegalStateException (
259
+ "Could not resolve specified class name argument [" + arg + "]" , ex );
260
+ }
230
261
}
231
- }
232
- else {
233
262
// Consider adding logic to determine the class of the typeArg, if possible.
234
263
// For now, just fall back...
235
264
return method .getReturnType ();
0 commit comments