1
1
/*
2
- * Copyright 2002-2015 the original author or authors.
2
+ * Copyright 2002-2016 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
package org .springframework .beans .factory .annotation ;
18
18
19
19
import java .lang .reflect .Method ;
20
+ import java .util .function .Predicate ;
20
21
22
+ import org .springframework .beans .BeansException ;
21
23
import org .springframework .beans .factory .BeanFactory ;
22
24
import org .springframework .beans .factory .BeanFactoryUtils ;
23
25
import org .springframework .beans .factory .NoSuchBeanDefinitionException ;
26
+ import org .springframework .beans .factory .NoUniqueBeanDefinitionException ;
24
27
import org .springframework .beans .factory .config .BeanDefinition ;
28
+ import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
25
29
import org .springframework .beans .factory .config .ConfigurableListableBeanFactory ;
26
30
import org .springframework .beans .factory .support .AbstractBeanDefinition ;
27
31
import org .springframework .beans .factory .support .AutowireCandidateQualifier ;
28
32
import org .springframework .beans .factory .support .RootBeanDefinition ;
29
33
import org .springframework .core .annotation .AnnotationUtils ;
30
- import org .springframework .util .ObjectUtils ;
34
+ import org .springframework .util .Assert ;
31
35
32
36
/**
33
37
* Convenience methods performing bean lookups related to annotations, for example
34
38
* Spring's {@link Qualifier @Qualifier} annotation.
35
39
*
36
- * @author Chris Beams
37
40
* @author Juergen Hoeller
41
+ * @author Chris Beams
38
42
* @since 3.1.2
39
43
* @see BeanFactoryUtils
40
44
*/
41
- public class BeanFactoryAnnotationUtils {
45
+ public abstract class BeanFactoryAnnotationUtils {
42
46
43
47
/**
44
48
* Obtain a bean of type {@code T} from the given {@code BeanFactory} declaring a
@@ -48,9 +52,16 @@ public class BeanFactoryAnnotationUtils {
48
52
* @param beanType the type of bean to retrieve
49
53
* @param qualifier the qualifier for selecting between multiple bean matches
50
54
* @return the matching bean of type {@code T} (never {@code null})
55
+ * @throws NoUniqueBeanDefinitionException if multiple matching beans of type {@code T} found
51
56
* @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
57
+ * @throws BeansException if the bean could not be created
58
+ * @see BeanFactory#getBean(Class)
52
59
*/
53
- public static <T > T qualifiedBeanOfType (BeanFactory beanFactory , Class <T > beanType , String qualifier ) {
60
+ public static <T > T qualifiedBeanOfType (BeanFactory beanFactory , Class <T > beanType , String qualifier )
61
+ throws BeansException {
62
+
63
+ Assert .notNull (beanFactory , "BeanFactory must not be null" );
64
+
54
65
if (beanFactory instanceof ConfigurableListableBeanFactory ) {
55
66
// Full qualifier matching supported.
56
67
return qualifiedBeanOfType ((ConfigurableListableBeanFactory ) beanFactory , beanType , qualifier );
@@ -74,16 +85,14 @@ else if (beanFactory.containsBean(qualifier)) {
74
85
* @param beanType the type of bean to retrieve
75
86
* @param qualifier the qualifier for selecting between multiple bean matches
76
87
* @return the matching bean of type {@code T} (never {@code null})
77
- * @throws NoSuchBeanDefinitionException if no matching bean of type {@code T} found
78
88
*/
79
89
private static <T > T qualifiedBeanOfType (ConfigurableListableBeanFactory bf , Class <T > beanType , String qualifier ) {
80
90
String [] candidateBeans = BeanFactoryUtils .beanNamesForTypeIncludingAncestors (bf , beanType );
81
91
String matchingBean = null ;
82
92
for (String beanName : candidateBeans ) {
83
- if (isQualifierMatch (qualifier , beanName , bf )) {
93
+ if (isQualifierMatch (qualifier :: equals , beanName , bf )) {
84
94
if (matchingBean != null ) {
85
- throw new NoSuchBeanDefinitionException (qualifier , "No unique " + beanType .getSimpleName () +
86
- " bean found for qualifier '" + qualifier + "'" );
95
+ throw new NoUniqueBeanDefinitionException (beanType , matchingBean , beanName );
87
96
}
88
97
matchingBean = beanName ;
89
98
}
@@ -105,40 +114,54 @@ else if (bf.containsBean(qualifier)) {
105
114
* Check whether the named bean declares a qualifier of the given name.
106
115
* @param qualifier the qualifier to match
107
116
* @param beanName the name of the candidate bean
108
- * @param bf the {@code BeanFactory} from which to retrieve the named bean
117
+ * @param beanFactory the {@code BeanFactory} from which to retrieve the named bean
109
118
* @return {@code true} if either the bean definition (in the XML case)
110
119
* or the bean's factory method (in the {@code @Bean} case) defines a matching
111
120
* qualifier value (through {@code <qualifier>} or {@code @Qualifier})
121
+ * @since 5.0
112
122
*/
113
- private static boolean isQualifierMatch (String qualifier , String beanName , ConfigurableListableBeanFactory bf ) {
114
- if (bf .containsBean (beanName )) {
123
+ public static boolean isQualifierMatch (Predicate <String > qualifier , String beanName , BeanFactory beanFactory ) {
124
+ // Try quick bean name or alias match first...
125
+ if (qualifier .test (beanName )) {
126
+ return true ;
127
+ }
128
+ if (beanFactory != null ) {
129
+ for (String alias : beanFactory .getAliases (beanName )) {
130
+ if (qualifier .test (alias )) {
131
+ return true ;
132
+ }
133
+ }
115
134
try {
116
- BeanDefinition bd = bf .getMergedBeanDefinition (beanName );
117
- // Explicit qualifier metadata on bean definition? (typically in XML definition)
118
- if (bd instanceof AbstractBeanDefinition ) {
119
- AbstractBeanDefinition abd = (AbstractBeanDefinition ) bd ;
120
- AutowireCandidateQualifier candidate = abd .getQualifier (Qualifier .class .getName ());
121
- if ((candidate != null && qualifier .equals (candidate .getAttribute (AutowireCandidateQualifier .VALUE_KEY ))) ||
122
- qualifier .equals (beanName ) || ObjectUtils .containsElement (bf .getAliases (beanName ), qualifier )) {
123
- return true ;
135
+ if (beanFactory instanceof ConfigurableBeanFactory ) {
136
+ BeanDefinition bd = ((ConfigurableBeanFactory ) beanFactory ).getMergedBeanDefinition (beanName );
137
+ // Explicit qualifier metadata on bean definition? (typically in XML definition)
138
+ if (bd instanceof AbstractBeanDefinition ) {
139
+ AbstractBeanDefinition abd = (AbstractBeanDefinition ) bd ;
140
+ AutowireCandidateQualifier candidate = abd .getQualifier (Qualifier .class .getName ());
141
+ if (candidate != null ) {
142
+ Object value = candidate .getAttribute (AutowireCandidateQualifier .VALUE_KEY );
143
+ if (value != null && qualifier .test (value .toString ())) {
144
+ return true ;
145
+ }
146
+ }
124
147
}
125
- }
126
- // Corresponding qualifier on factory method? (typically in configuration class)
127
- if ( bd instanceof RootBeanDefinition ) {
128
- Method factoryMethod = (( RootBeanDefinition ) bd ). getResolvedFactoryMethod ();
129
- if ( factoryMethod != null ) {
130
- Qualifier targetAnnotation = AnnotationUtils . getAnnotation ( factoryMethod , Qualifier . class );
131
- if (targetAnnotation != null ) {
132
- return qualifier . equals ( targetAnnotation . value ());
148
+ // Corresponding qualifier on factory method? (typically in configuration class)
149
+ if ( bd instanceof RootBeanDefinition ) {
150
+ Method factoryMethod = (( RootBeanDefinition ) bd ). getResolvedFactoryMethod ();
151
+ if ( factoryMethod != null ) {
152
+ Qualifier targetAnnotation = AnnotationUtils . getAnnotation ( factoryMethod , Qualifier . class );
153
+ if ( targetAnnotation != null ) {
154
+ return qualifier . test (targetAnnotation . value ());
155
+ }
133
156
}
134
157
}
135
158
}
136
159
// Corresponding qualifier on bean implementation class? (for custom user types)
137
- Class <?> beanType = bf .getType (beanName );
160
+ Class <?> beanType = beanFactory .getType (beanName );
138
161
if (beanType != null ) {
139
162
Qualifier targetAnnotation = AnnotationUtils .getAnnotation (beanType , Qualifier .class );
140
163
if (targetAnnotation != null ) {
141
- return qualifier .equals (targetAnnotation .value ());
164
+ return qualifier .test (targetAnnotation .value ());
142
165
}
143
166
}
144
167
}
0 commit comments