30
30
import java .util .function .Predicate ;
31
31
import java .util .function .Supplier ;
32
32
33
- import org .apache .commons .logging .Log ;
34
- import org .apache .commons .logging .LogFactory ;
35
-
33
+ import org .springframework .beans .BeanUtils ;
36
34
import org .springframework .beans .factory .FactoryBean ;
37
35
import org .springframework .beans .factory .annotation .Autowired ;
38
36
import org .springframework .beans .factory .config .BeanDefinition ;
39
37
import org .springframework .beans .factory .config .BeanReference ;
40
38
import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
41
39
import org .springframework .beans .factory .config .ConstructorArgumentValues ;
42
40
import org .springframework .beans .factory .config .ConstructorArgumentValues .ValueHolder ;
41
+ import org .springframework .beans .factory .config .RuntimeBeanReference ;
43
42
import org .springframework .beans .factory .support .AbstractBeanDefinition ;
44
43
import org .springframework .beans .factory .support .RegisteredBean ;
45
44
import org .springframework .beans .factory .support .RootBeanDefinition ;
62
61
*/
63
62
class ConstructorOrFactoryMethodResolver {
64
63
65
- private static final Log logger = LogFactory
66
- .getLog (ConstructorOrFactoryMethodResolver .class );
67
-
68
-
69
64
private final ConfigurableBeanFactory beanFactory ;
70
65
66
+ @ Nullable
71
67
private final ClassLoader classLoader ;
72
68
73
69
74
70
ConstructorOrFactoryMethodResolver (ConfigurableBeanFactory beanFactory ) {
75
71
this .beanFactory = beanFactory ;
76
- this .classLoader = (beanFactory .getBeanClassLoader () != null )
77
- ? beanFactory .getBeanClassLoader () : ClassUtils .getDefaultClassLoader ();
72
+ this .classLoader = (beanFactory .getBeanClassLoader () != null ?
73
+ beanFactory .getBeanClassLoader () : ClassUtils .getDefaultClassLoader () );
78
74
}
79
75
80
76
77
+ @ Nullable
81
78
Executable resolve (BeanDefinition beanDefinition ) {
82
79
Supplier <ResolvableType > beanType = () -> getBeanType (beanDefinition );
83
- List <ResolvableType > valueTypes = beanDefinition .hasConstructorArgumentValues ()
84
- ? determineParameterValueTypes (
85
- beanDefinition .getConstructorArgumentValues ())
86
- : Collections .emptyList ();
80
+ List <ResolvableType > valueTypes = (beanDefinition .hasConstructorArgumentValues () ?
81
+ determineParameterValueTypes (beanDefinition .getConstructorArgumentValues ()) :
82
+ Collections .emptyList ());
87
83
Method resolvedFactoryMethod = resolveFactoryMethod (beanDefinition , valueTypes );
88
84
if (resolvedFactoryMethod != null ) {
89
85
return resolvedFactoryMethod ;
90
86
}
87
+
91
88
Class <?> factoryBeanClass = getFactoryBeanClass (beanDefinition );
92
- if (factoryBeanClass != null && !factoryBeanClass
93
- .equals (beanDefinition .getResolvableType ().toClass ())) {
89
+ if (factoryBeanClass != null && !factoryBeanClass .equals (beanDefinition .getResolvableType ().toClass ())) {
94
90
ResolvableType resolvableType = beanDefinition .getResolvableType ();
95
91
boolean isCompatible = ResolvableType .forClass (factoryBeanClass )
96
92
.as (FactoryBean .class ).getGeneric (0 ).isAssignableFrom (resolvableType );
97
- Assert .state (isCompatible ,
98
- () -> String .format (
99
- "Incompatible target type '%s' for factory bean '%s'" ,
100
- resolvableType .toClass ().getName (),
101
- factoryBeanClass .getName ()));
102
- return resolveConstructor (() -> ResolvableType .forClass (factoryBeanClass ),
103
- valueTypes );
93
+ Assert .state (isCompatible , () -> String .format (
94
+ "Incompatible target type '%s' for factory bean '%s'" ,
95
+ resolvableType .toClass ().getName (), factoryBeanClass .getName ()));
96
+ return resolveConstructor (() -> ResolvableType .forClass (factoryBeanClass ), valueTypes );
104
97
}
98
+
105
99
Executable resolvedConstructor = resolveConstructor (beanType , valueTypes );
106
100
if (resolvedConstructor != null ) {
107
101
return resolvedConstructor ;
108
102
}
109
- Executable resolvedConstructorOrFactoryMethod = getField (beanDefinition ,
110
- "resolvedConstructorOrFactoryMethod" , Executable .class );
111
- if (resolvedConstructorOrFactoryMethod != null ) {
112
- logger .error (
113
- "resolvedConstructorOrFactoryMethod required for " + beanDefinition );
114
- return resolvedConstructorOrFactoryMethod ;
103
+
104
+ Field field = ReflectionUtils .findField (RootBeanDefinition .class , "resolvedConstructorOrFactoryMethod" );
105
+ if (field != null ) {
106
+ ReflectionUtils .makeAccessible (field );
107
+ return (Executable ) ReflectionUtils .getField (field , beanDefinition );
115
108
}
109
+
116
110
return null ;
117
111
}
118
112
@@ -132,15 +126,19 @@ private ResolvableType determineParameterValueType(ValueHolder valueHolder) {
132
126
return ResolvableType .forClass (loadClass (valueHolder .getType ()));
133
127
}
134
128
Object value = valueHolder .getValue ();
135
- if (value instanceof BeanReference ) {
136
- return ResolvableType .forClass (this .beanFactory
137
- .getType (((BeanReference ) value ).getBeanName (), false ));
129
+ if (value instanceof BeanReference br ) {
130
+ if (value instanceof RuntimeBeanReference rbr ) {
131
+ if (rbr .getBeanType () != null ) {
132
+ return ResolvableType .forClass (rbr .getBeanType ());
133
+ }
134
+ }
135
+ return ResolvableType .forClass (this .beanFactory .getType (br .getBeanName (), false ));
138
136
}
139
- if (value instanceof BeanDefinition ) {
140
- return extractTypeFromBeanDefinition (getBeanType (( BeanDefinition ) value ));
137
+ if (value instanceof BeanDefinition bd ) {
138
+ return extractTypeFromBeanDefinition (getBeanType (bd ));
141
139
}
142
- if (value instanceof Class <?>) {
143
- return ResolvableType .forClassWithGenerics (Class .class , ( Class <?>) value );
140
+ if (value instanceof Class <?> clazz ) {
141
+ return ResolvableType .forClassWithGenerics (Class .class , clazz );
144
142
}
145
143
return ResolvableType .forInstance (value );
146
144
}
@@ -153,9 +151,7 @@ private ResolvableType extractTypeFromBeanDefinition(ResolvableType type) {
153
151
}
154
152
155
153
@ Nullable
156
- private Method resolveFactoryMethod (BeanDefinition beanDefinition ,
157
- List <ResolvableType > valueTypes ) {
158
-
154
+ private Method resolveFactoryMethod (BeanDefinition beanDefinition , List <ResolvableType > valueTypes ) {
159
155
if (beanDefinition instanceof RootBeanDefinition rbd ) {
160
156
Method resolvedFactoryMethod = rbd .getResolvedFactoryMethod ();
161
157
if (resolvedFactoryMethod != null ) {
@@ -165,15 +161,13 @@ private Method resolveFactoryMethod(BeanDefinition beanDefinition,
165
161
String factoryMethodName = beanDefinition .getFactoryMethodName ();
166
162
if (factoryMethodName != null ) {
167
163
String factoryBeanName = beanDefinition .getFactoryBeanName ();
168
- Class <?> beanClass = getBeanClass ((factoryBeanName != null )
169
- ? this .beanFactory .getMergedBeanDefinition (factoryBeanName )
170
- : beanDefinition );
164
+ Class <?> beanClass = getBeanClass (factoryBeanName != null ?
165
+ this .beanFactory .getMergedBeanDefinition (factoryBeanName ) : beanDefinition );
171
166
List <Method > methods = new ArrayList <>();
172
167
Assert .state (beanClass != null ,
173
168
() -> "Failed to determine bean class of " + beanDefinition );
174
169
ReflectionUtils .doWithMethods (beanClass , methods ::add ,
175
- method -> isFactoryMethodCandidate (beanClass , method ,
176
- factoryMethodName ));
170
+ method -> isFactoryMethodCandidate (beanClass , method , factoryMethodName ));
177
171
if (methods .size () >= 1 ) {
178
172
Function <Method , List <ResolvableType >> parameterTypesFactory = method -> {
179
173
List <ResolvableType > types = new ArrayList <>();
@@ -182,16 +176,13 @@ private Method resolveFactoryMethod(BeanDefinition beanDefinition,
182
176
}
183
177
return types ;
184
178
};
185
- return (Method ) resolveFactoryMethod (methods , parameterTypesFactory ,
186
- valueTypes );
179
+ return (Method ) resolveFactoryMethod (methods , parameterTypesFactory , valueTypes );
187
180
}
188
181
}
189
182
return null ;
190
183
}
191
184
192
- private boolean isFactoryMethodCandidate (Class <?> beanClass , Method method ,
193
- String factoryMethodName ) {
194
-
185
+ private boolean isFactoryMethodCandidate (Class <?> beanClass , Method method , String factoryMethodName ) {
195
186
if (method .getName ().equals (factoryMethodName )) {
196
187
if (Modifier .isStatic (method .getModifiers ())) {
197
188
return method .getDeclaringClass ().equals (beanClass );
@@ -202,9 +193,7 @@ private boolean isFactoryMethodCandidate(Class<?> beanClass, Method method,
202
193
}
203
194
204
195
@ Nullable
205
- private Executable resolveConstructor (Supplier <ResolvableType > beanType ,
206
- List <ResolvableType > valueTypes ) {
207
-
196
+ private Executable resolveConstructor (Supplier <ResolvableType > beanType , List <ResolvableType > valueTypes ) {
208
197
Class <?> type = ClassUtils .getUserClass (beanType .get ().toClass ());
209
198
Constructor <?>[] constructors = type .getDeclaredConstructors ();
210
199
if (constructors .length == 1 ) {
@@ -240,47 +229,41 @@ private Executable resolveConstructor(Supplier<ResolvableType> beanType,
240
229
List <? extends Executable > typeConversionFallbackMatches = Arrays
241
230
.stream (constructors )
242
231
.filter (executable -> match (parameterTypesFactory .apply (executable ),
243
- valueTypes ,
244
- ConstructorOrFactoryMethodResolver .FallbackMode .TYPE_CONVERSION ))
232
+ valueTypes , FallbackMode .TYPE_CONVERSION ))
245
233
.toList ();
246
234
return (typeConversionFallbackMatches .size () == 1 )
247
235
? typeConversionFallbackMatches .get (0 ) : null ;
248
236
}
249
237
238
+ @ Nullable
250
239
private Executable resolveFactoryMethod (List <Method > executables ,
251
240
Function <Method , List <ResolvableType >> parameterTypesFactory ,
252
241
List <ResolvableType > valueTypes ) {
253
242
254
243
List <? extends Executable > matches = executables .stream ()
255
- .filter (executable -> match (parameterTypesFactory .apply (executable ),
256
- valueTypes , ConstructorOrFactoryMethodResolver .FallbackMode .NONE ))
244
+ .filter (executable -> match (parameterTypesFactory .apply (executable ), valueTypes , FallbackMode .NONE ))
257
245
.toList ();
258
246
if (matches .size () == 1 ) {
259
247
return matches .get (0 );
260
248
}
261
249
List <? extends Executable > assignableElementFallbackMatches = executables .stream ()
262
250
.filter (executable -> match (parameterTypesFactory .apply (executable ),
263
- valueTypes ,
264
- ConstructorOrFactoryMethodResolver .FallbackMode .ASSIGNABLE_ELEMENT ))
251
+ valueTypes , FallbackMode .ASSIGNABLE_ELEMENT ))
265
252
.toList ();
266
253
if (assignableElementFallbackMatches .size () == 1 ) {
267
254
return assignableElementFallbackMatches .get (0 );
268
255
}
269
256
List <? extends Executable > typeConversionFallbackMatches = executables .stream ()
270
257
.filter (executable -> match (parameterTypesFactory .apply (executable ),
271
- valueTypes ,
272
- ConstructorOrFactoryMethodResolver .FallbackMode .TYPE_CONVERSION ))
258
+ valueTypes , FallbackMode .TYPE_CONVERSION ))
273
259
.toList ();
274
260
Assert .state (typeConversionFallbackMatches .size () <= 1 ,
275
- () -> "Multiple matches with parameters '" + valueTypes + "': "
276
- + typeConversionFallbackMatches );
277
- return (typeConversionFallbackMatches .size () == 1 )
278
- ? typeConversionFallbackMatches .get (0 ) : null ;
261
+ () -> "Multiple matches with parameters '" + valueTypes + "': " + typeConversionFallbackMatches );
262
+ return (typeConversionFallbackMatches .size () == 1 ? typeConversionFallbackMatches .get (0 ) : null );
279
263
}
280
264
281
- private boolean match (List <ResolvableType > parameterTypes ,
282
- List <ResolvableType > valueTypes ,
283
- ConstructorOrFactoryMethodResolver .FallbackMode fallbackMode ) {
265
+ private boolean match (
266
+ List <ResolvableType > parameterTypes , List <ResolvableType > valueTypes , FallbackMode fallbackMode ) {
284
267
285
268
if (parameterTypes .size () != valueTypes .size ()) {
286
269
return false ;
@@ -293,17 +276,14 @@ private boolean match(List<ResolvableType> parameterTypes,
293
276
return true ;
294
277
}
295
278
296
- private boolean isMatch (ResolvableType parameterType , ResolvableType valueType ,
297
- ConstructorOrFactoryMethodResolver .FallbackMode fallbackMode ) {
298
-
279
+ private boolean isMatch (ResolvableType parameterType , ResolvableType valueType , FallbackMode fallbackMode ) {
299
280
if (isAssignable (valueType ).test (parameterType )) {
300
281
return true ;
301
282
}
302
283
return switch (fallbackMode ) {
303
- case ASSIGNABLE_ELEMENT -> isAssignable (valueType )
304
- .test (extractElementType (parameterType ));
305
- case TYPE_CONVERSION -> typeConversionFallback (valueType ).test (parameterType );
306
- default -> false ;
284
+ case ASSIGNABLE_ELEMENT -> isAssignable (valueType ).test (extractElementType (parameterType ));
285
+ case TYPE_CONVERSION -> typeConversionFallback (valueType ).test (parameterType );
286
+ default -> false ;
307
287
};
308
288
}
309
289
@@ -323,12 +303,10 @@ private ResolvableType extractElementType(ResolvableType parameterType) {
323
303
324
304
private Predicate <ResolvableType > typeConversionFallback (ResolvableType valueType ) {
325
305
return parameterType -> {
326
- if (valueOrCollection (valueType , this ::isStringForClassFallback )
327
- .test (parameterType )) {
306
+ if (valueOrCollection (valueType , this ::isStringForClassFallback ).test (parameterType )) {
328
307
return true ;
329
308
}
330
- return valueOrCollection (valueType , this ::isSimpleConvertibleType )
331
- .test (parameterType );
309
+ return valueOrCollection (valueType , this ::isSimpleValueType ).test (parameterType );
332
310
};
333
311
}
334
312
@@ -339,12 +317,10 @@ private Predicate<ResolvableType> valueOrCollection(ResolvableType valueType,
339
317
if (predicateProvider .apply (valueType ).test (parameterType )) {
340
318
return true ;
341
319
}
342
- if (predicateProvider .apply (extractElementType (valueType ))
343
- .test (extractElementType (parameterType ))) {
320
+ if (predicateProvider .apply (extractElementType (valueType )).test (extractElementType (parameterType ))) {
344
321
return true ;
345
322
}
346
- return (predicateProvider .apply (valueType )
347
- .test (extractElementType (parameterType )));
323
+ return (predicateProvider .apply (valueType ).test (extractElementType (parameterType )));
348
324
};
349
325
}
350
326
@@ -358,34 +334,32 @@ private Predicate<ResolvableType> valueOrCollection(ResolvableType valueType,
358
334
* parameter
359
335
*/
360
336
private Predicate <ResolvableType > isStringForClassFallback (ResolvableType valueType ) {
361
- return parameterType -> (valueType .isAssignableFrom (String .class )
362
- && parameterType .isAssignableFrom (Class .class ));
337
+ return parameterType -> (valueType .isAssignableFrom (String .class ) &&
338
+ parameterType .isAssignableFrom (Class .class ));
363
339
}
364
340
365
- private Predicate <ResolvableType > isSimpleConvertibleType (ResolvableType valueType ) {
366
- return parameterType -> isSimpleConvertibleType ( parameterType .toClass ())
367
- && isSimpleConvertibleType (valueType .toClass ());
341
+ private Predicate <ResolvableType > isSimpleValueType (ResolvableType valueType ) {
342
+ return parameterType -> ( BeanUtils . isSimpleValueType ( parameterType .toClass ()) &&
343
+ BeanUtils . isSimpleValueType (valueType .toClass () ));
368
344
}
369
345
370
346
@ Nullable
371
347
private Class <?> getFactoryBeanClass (BeanDefinition beanDefinition ) {
372
348
if (beanDefinition instanceof RootBeanDefinition rbd ) {
373
349
if (rbd .hasBeanClass ()) {
374
350
Class <?> beanClass = rbd .getBeanClass ();
375
- return FactoryBean .class .isAssignableFrom (beanClass ) ? beanClass : null ;
351
+ return ( FactoryBean .class .isAssignableFrom (beanClass ) ? beanClass : null ) ;
376
352
}
377
353
}
378
354
return null ;
379
355
}
380
356
381
357
@ Nullable
382
358
private Class <?> getBeanClass (BeanDefinition beanDefinition ) {
383
- if (beanDefinition instanceof AbstractBeanDefinition abd ) {
384
- return abd .hasBeanClass () ? abd .getBeanClass ()
385
- : loadClass (abd .getBeanClassName ());
359
+ if (beanDefinition instanceof AbstractBeanDefinition abd && abd .hasBeanClass ()) {
360
+ return abd .getBeanClass ();
386
361
}
387
- return (beanDefinition .getBeanClassName () != null )
388
- ? loadClass (beanDefinition .getBeanClassName ()) : null ;
362
+ return (beanDefinition .getBeanClassName () != null ? loadClass (beanDefinition .getBeanClassName ()) : null );
389
363
}
390
364
391
365
private ResolvableType getBeanType (BeanDefinition beanDefinition ) {
@@ -416,21 +390,6 @@ private Class<?> loadClass(String beanClassName) {
416
390
}
417
391
418
392
@ Nullable
419
- private <T > T getField (BeanDefinition beanDefinition , String fieldName ,
420
- Class <T > targetType ) {
421
-
422
- Field field = ReflectionUtils .findField (RootBeanDefinition .class , fieldName );
423
- ReflectionUtils .makeAccessible (field );
424
- return targetType .cast (ReflectionUtils .getField (field , beanDefinition ));
425
- }
426
-
427
- private static boolean isSimpleConvertibleType (Class <?> type ) {
428
- return (type .isPrimitive () && type != void .class ) || type == Double .class
429
- || type == Float .class || type == Long .class || type == Integer .class
430
- || type == Short .class || type == Character .class || type == Byte .class
431
- || type == Boolean .class || type == String .class ;
432
- }
433
-
434
393
static Executable resolve (RegisteredBean registeredBean ) {
435
394
return new ConstructorOrFactoryMethodResolver (registeredBean .getBeanFactory ())
436
395
.resolve (registeredBean .getMergedBeanDefinition ());
@@ -444,7 +403,6 @@ enum FallbackMode {
444
403
ASSIGNABLE_ELEMENT ,
445
404
446
405
TYPE_CONVERSION
447
-
448
406
}
449
407
450
408
}
0 commit comments