24
24
import java .util .Collections ;
25
25
import java .util .HashMap ;
26
26
import java .util .HashSet ;
27
+ import java .util .LinkedHashMap ;
27
28
import java .util .LinkedHashSet ;
28
29
import java .util .List ;
29
30
import java .util .Locale ;
30
31
import java .util .Map ;
31
32
import java .util .Map .Entry ;
32
33
import java .util .Set ;
34
+ import java .util .function .BiPredicate ;
33
35
import java .util .function .Predicate ;
34
36
35
37
import org .springframework .aop .scope .ScopedProxyUtils ;
36
38
import org .springframework .beans .factory .BeanFactory ;
37
39
import org .springframework .beans .factory .HierarchicalBeanFactory ;
38
40
import org .springframework .beans .factory .ListableBeanFactory ;
41
+ import org .springframework .beans .factory .NoSuchBeanDefinitionException ;
39
42
import org .springframework .beans .factory .config .BeanDefinition ;
40
43
import org .springframework .beans .factory .config .ConfigurableListableBeanFactory ;
41
44
import org .springframework .beans .factory .config .SingletonBeanRegistry ;
@@ -211,26 +214,30 @@ protected final MatchResult getMatchingBeans(Spec<?> spec) {
211
214
Set <String > beansIgnoredByType = getNamesOfBeansIgnoredByType (classLoader , beanFactory , considerHierarchy ,
212
215
spec .getIgnoredTypes (), parameterizedContainers );
213
216
for (String type : spec .getTypes ()) {
214
- Collection <String > typeMatches = getBeanNamesForType (classLoader , considerHierarchy , beanFactory , type ,
215
- parameterizedContainers );
216
- typeMatches
217
- .removeIf ((match ) -> beansIgnoredByType .contains (match ) || ScopedProxyUtils .isScopedTarget (match ));
218
- if (typeMatches .isEmpty ()) {
217
+ Map <String , BeanDefinition > typeMatchedDefinitions = getBeanDefinitionsForType (classLoader ,
218
+ considerHierarchy , beanFactory , type , parameterizedContainers );
219
+ Set <String > typeMatchedNames = matchedNamesFrom (typeMatchedDefinitions ,
220
+ (name , definition ) -> !beansIgnoredByType .contains (name ) && !ScopedProxyUtils .isScopedTarget (name )
221
+ && (definition == null || definition .isAutowireCandidate ()));
222
+ if (typeMatchedNames .isEmpty ()) {
219
223
result .recordUnmatchedType (type );
220
224
}
221
225
else {
222
- result .recordMatchedType (type , typeMatches );
226
+ result .recordMatchedType (type , typeMatchedNames );
223
227
}
224
228
}
225
229
for (String annotation : spec .getAnnotations ()) {
226
- Set <String > annotationMatches = getBeanNamesForAnnotation (classLoader , beanFactory , annotation ,
227
- considerHierarchy );
228
- annotationMatches .removeAll (beansIgnoredByType );
229
- if (annotationMatches .isEmpty ()) {
230
+ Map <String , BeanDefinition > annotationMatchedDefinitions = getBeanDefinitionsForAnnotation (classLoader ,
231
+ beanFactory , annotation , considerHierarchy );
232
+ Set <String > annotationMatchedNames = matchedNamesFrom (annotationMatchedDefinitions ,
233
+ (name , definition ) -> !beansIgnoredByType .contains (name )
234
+ && (definition == null || definition .isAutowireCandidate ()));
235
+ if (annotationMatchedNames .isEmpty ()) {
230
236
result .recordUnmatchedAnnotation (annotation );
231
237
}
232
238
else {
233
- result .recordMatchedAnnotation (annotation , annotationMatches );
239
+ result .recordMatchedAnnotation (annotation , annotationMatchedNames );
240
+
234
241
}
235
242
}
236
243
for (String beanName : spec .getNames ()) {
@@ -244,63 +251,76 @@ protected final MatchResult getMatchingBeans(Spec<?> spec) {
244
251
return result ;
245
252
}
246
253
254
+ private Set <String > matchedNamesFrom (Map <String , BeanDefinition > namedDefinitions ,
255
+ BiPredicate <String , BeanDefinition > filter ) {
256
+ Set <String > matchedNames = new LinkedHashSet <>(namedDefinitions .size ());
257
+ for (Entry <String , BeanDefinition > namedDefinition : namedDefinitions .entrySet ()) {
258
+ if (filter .test (namedDefinition .getKey (), namedDefinition .getValue ())) {
259
+ matchedNames .add (namedDefinition .getKey ());
260
+ }
261
+ }
262
+ return matchedNames ;
263
+ }
264
+
247
265
private Set <String > getNamesOfBeansIgnoredByType (ClassLoader classLoader , ListableBeanFactory beanFactory ,
248
266
boolean considerHierarchy , Set <String > ignoredTypes , Set <Class <?>> parameterizedContainers ) {
249
267
Set <String > result = null ;
250
268
for (String ignoredType : ignoredTypes ) {
251
- Collection <String > ignoredNames = getBeanNamesForType (classLoader , considerHierarchy , beanFactory ,
252
- ignoredType , parameterizedContainers );
269
+ Collection <String > ignoredNames = getBeanDefinitionsForType (classLoader , considerHierarchy , beanFactory ,
270
+ ignoredType , parameterizedContainers )
271
+ .keySet ();
253
272
result = addAll (result , ignoredNames );
254
273
}
255
274
return (result != null ) ? result : Collections .emptySet ();
256
275
}
257
276
258
- private Set <String > getBeanNamesForType (ClassLoader classLoader , boolean considerHierarchy ,
277
+ private Map <String , BeanDefinition > getBeanDefinitionsForType (ClassLoader classLoader , boolean considerHierarchy ,
259
278
ListableBeanFactory beanFactory , String type , Set <Class <?>> parameterizedContainers ) throws LinkageError {
260
279
try {
261
- return getBeanNamesForType (beanFactory , considerHierarchy , resolve (type , classLoader ),
280
+ return getBeanDefinitionsForType (beanFactory , considerHierarchy , resolve (type , classLoader ),
262
281
parameterizedContainers );
263
282
}
264
283
catch (ClassNotFoundException | NoClassDefFoundError ex ) {
265
- return Collections .emptySet ();
284
+ return Collections .emptyMap ();
266
285
}
267
286
}
268
287
269
- private Set <String > getBeanNamesForType (ListableBeanFactory beanFactory , boolean considerHierarchy , Class <?> type ,
270
- Set <Class <?>> parameterizedContainers ) {
271
- Set <String > result = collectBeanNamesForType (beanFactory , considerHierarchy , type , parameterizedContainers ,
272
- null );
273
- return (result != null ) ? result : Collections .emptySet ();
288
+ private Map <String , BeanDefinition > getBeanDefinitionsForType (ListableBeanFactory beanFactory ,
289
+ boolean considerHierarchy , Class <?> type , Set <Class <?>> parameterizedContainers ) {
290
+ Map <String , BeanDefinition > result = collectBeanDefinitionsForType (beanFactory , considerHierarchy , type ,
291
+ parameterizedContainers , null );
292
+ return (result != null ) ? result : Collections .emptyMap ();
274
293
}
275
294
276
- private Set <String > collectBeanNamesForType (ListableBeanFactory beanFactory , boolean considerHierarchy ,
277
- Class <?> type , Set <Class <?>> parameterizedContainers , Set <String > result ) {
278
- result = addAll (result , beanFactory .getBeanNamesForType (type , true , false ));
295
+ private Map <String , BeanDefinition > collectBeanDefinitionsForType (ListableBeanFactory beanFactory ,
296
+ boolean considerHierarchy , Class <?> type , Set <Class <?>> parameterizedContainers ,
297
+ Map <String , BeanDefinition > result ) {
298
+ result = putAll (result , beanFactory .getBeanNamesForType (type , true , false ), beanFactory );
279
299
for (Class <?> container : parameterizedContainers ) {
280
300
ResolvableType generic = ResolvableType .forClassWithGenerics (container , type );
281
- result = addAll (result , beanFactory .getBeanNamesForType (generic , true , false ));
301
+ result = putAll (result , beanFactory .getBeanNamesForType (generic , true , false ), beanFactory );
282
302
}
283
303
if (considerHierarchy && beanFactory instanceof HierarchicalBeanFactory hierarchicalBeanFactory ) {
284
304
BeanFactory parent = hierarchicalBeanFactory .getParentBeanFactory ();
285
305
if (parent instanceof ListableBeanFactory listableBeanFactory ) {
286
- result = collectBeanNamesForType (listableBeanFactory , considerHierarchy , type , parameterizedContainers ,
287
- result );
306
+ result = collectBeanDefinitionsForType (listableBeanFactory , considerHierarchy , type ,
307
+ parameterizedContainers , result );
288
308
}
289
309
}
290
310
return result ;
291
311
}
292
312
293
- private Set <String > getBeanNamesForAnnotation (ClassLoader classLoader , ConfigurableListableBeanFactory beanFactory ,
294
- String type , boolean considerHierarchy ) throws LinkageError {
295
- Set <String > result = null ;
313
+ private Map <String , BeanDefinition > getBeanDefinitionsForAnnotation (ClassLoader classLoader ,
314
+ ConfigurableListableBeanFactory beanFactory , String type , boolean considerHierarchy ) throws LinkageError {
315
+ Map <String , BeanDefinition > result = null ;
296
316
try {
297
- result = collectBeanNamesForAnnotation (beanFactory , resolveAnnotationType (classLoader , type ),
317
+ result = collectBeanDefinitionsForAnnotation (beanFactory , resolveAnnotationType (classLoader , type ),
298
318
considerHierarchy , result );
299
319
}
300
320
catch (ClassNotFoundException ex ) {
301
321
// Continue
302
322
}
303
- return (result != null ) ? result : Collections .emptySet ();
323
+ return (result != null ) ? result : Collections .emptyMap ();
304
324
}
305
325
306
326
@ SuppressWarnings ("unchecked" )
@@ -309,13 +329,14 @@ private Class<? extends Annotation> resolveAnnotationType(ClassLoader classLoade
309
329
return (Class <? extends Annotation >) resolve (type , classLoader );
310
330
}
311
331
312
- private Set <String > collectBeanNamesForAnnotation (ListableBeanFactory beanFactory ,
313
- Class <? extends Annotation > annotationType , boolean considerHierarchy , Set <String > result ) {
314
- result = addAll (result , getBeanNamesForAnnotation (beanFactory , annotationType ));
332
+ private Map <String , BeanDefinition > collectBeanDefinitionsForAnnotation (ListableBeanFactory beanFactory ,
333
+ Class <? extends Annotation > annotationType , boolean considerHierarchy , Map <String , BeanDefinition > result ) {
334
+ result = putAll (result , getBeanNamesForAnnotation (beanFactory , annotationType ), beanFactory );
315
335
if (considerHierarchy ) {
316
336
BeanFactory parent = ((HierarchicalBeanFactory ) beanFactory ).getParentBeanFactory ();
317
337
if (parent instanceof ListableBeanFactory listableBeanFactory ) {
318
- result = collectBeanNamesForAnnotation (listableBeanFactory , annotationType , considerHierarchy , result );
338
+ result = collectBeanDefinitionsForAnnotation (listableBeanFactory , annotationType , considerHierarchy ,
339
+ result );
319
340
}
320
341
}
321
342
return result ;
@@ -453,12 +474,27 @@ private static Set<String> addAll(Set<String> result, Collection<String> additio
453
474
return result ;
454
475
}
455
476
456
- private static Set <String > addAll (Set <String > result , String [] additional ) {
457
- if (ObjectUtils .isEmpty (additional )) {
477
+ private static Map <String , BeanDefinition > putAll (Map <String , BeanDefinition > result , String [] beanNames ,
478
+ ListableBeanFactory beanFactory ) {
479
+ if (ObjectUtils .isEmpty (beanNames )) {
458
480
return result ;
459
481
}
460
- result = (result != null ) ? result : new LinkedHashSet <>();
461
- Collections .addAll (result , additional );
482
+ if (result == null ) {
483
+ result = new LinkedHashMap <>();
484
+ }
485
+ for (String beanName : beanNames ) {
486
+ if (beanFactory instanceof ConfigurableListableBeanFactory clbf ) {
487
+ try {
488
+ result .put (beanName , clbf .getBeanDefinition (beanName ));
489
+ }
490
+ catch (NoSuchBeanDefinitionException ex ) {
491
+ result .put (beanName , null );
492
+ }
493
+ }
494
+ else {
495
+ result .put (beanName , null );
496
+ }
497
+ }
462
498
return result ;
463
499
}
464
500
0 commit comments