1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.beans.factory.annotation;
18
19 import java.lang.annotation.Annotation;
20 import java.lang.reflect.Method;
21 import java.util.LinkedHashSet;
22 import java.util.Map;
23 import java.util.Set;
24
25 import org.springframework.beans.SimpleTypeConverter;
26 import org.springframework.beans.TypeConverter;
27 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
28 import org.springframework.beans.factory.config.BeanDefinitionHolder;
29 import org.springframework.beans.factory.config.DependencyDescriptor;
30 import org.springframework.beans.factory.support.AutowireCandidateQualifier;
31 import org.springframework.beans.factory.support.AutowireCandidateResolver;
32 import org.springframework.beans.factory.support.GenericTypeAwareAutowireCandidateResolver;
33 import org.springframework.beans.factory.support.RootBeanDefinition;
34 import org.springframework.core.MethodParameter;
35 import org.springframework.core.annotation.AnnotationUtils;
36 import org.springframework.util.Assert;
37 import org.springframework.util.ClassUtils;
38 import org.springframework.util.ObjectUtils;
39 import org.springframework.util.StringUtils;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwareAutowireCandidateResolver {
56
57 private final Set<Class<? extends Annotation>> qualifierTypes = new LinkedHashSet<Class<? extends Annotation>>(2);
58
59 private Class<? extends Annotation> valueAnnotationType = Value.class;
60
61
62
63
64
65
66
67 @SuppressWarnings("unchecked")
68 public QualifierAnnotationAutowireCandidateResolver() {
69 this.qualifierTypes.add(Qualifier.class);
70 try {
71 this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
72 QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
73 }
74 catch (ClassNotFoundException ex) {
75
76 }
77 }
78
79
80
81
82
83
84 public QualifierAnnotationAutowireCandidateResolver(Class<? extends Annotation> qualifierType) {
85 Assert.notNull(qualifierType, "'qualifierType' must not be null");
86 this.qualifierTypes.add(qualifierType);
87 }
88
89
90
91
92
93
94 public QualifierAnnotationAutowireCandidateResolver(Set<Class<? extends Annotation>> qualifierTypes) {
95 Assert.notNull(qualifierTypes, "'qualifierTypes' must not be null");
96 this.qualifierTypes.addAll(qualifierTypes);
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110 public void addQualifierType(Class<? extends Annotation> qualifierType) {
111 this.qualifierTypes.add(qualifierType);
112 }
113
114
115
116
117
118
119
120
121
122
123 public void setValueAnnotationType(Class<? extends Annotation> valueAnnotationType) {
124 this.valueAnnotationType = valueAnnotationType;
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 @Override
141 public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
142 boolean match = super.isAutowireCandidate(bdHolder, descriptor);
143 if (match && descriptor != null) {
144 match = checkQualifiers(bdHolder, descriptor.getAnnotations());
145 if (match) {
146 MethodParameter methodParam = descriptor.getMethodParameter();
147 if (methodParam != null) {
148 Method method = methodParam.getMethod();
149 if (method == null || void.class.equals(method.getReturnType())) {
150 match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
151 }
152 }
153 }
154 }
155 return match;
156 }
157
158
159
160
161 protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
162 if (ObjectUtils.isEmpty(annotationsToSearch)) {
163 return true;
164 }
165 SimpleTypeConverter typeConverter = new SimpleTypeConverter();
166 for (Annotation annotation : annotationsToSearch) {
167 Class<? extends Annotation> type = annotation.annotationType();
168 boolean checkMeta = true;
169 boolean fallbackToMeta = false;
170 if (isQualifier(type)) {
171 if (!checkQualifier(bdHolder, annotation, typeConverter)) {
172 fallbackToMeta = true;
173 }
174 else {
175 checkMeta = false;
176 }
177 }
178 if (checkMeta) {
179 boolean foundMeta = false;
180 for (Annotation metaAnn : type.getAnnotations()) {
181 Class<? extends Annotation> metaType = metaAnn.annotationType();
182 if (isQualifier(metaType)) {
183 foundMeta = true;
184
185
186 if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
187 !checkQualifier(bdHolder, metaAnn, typeConverter)) {
188 return false;
189 }
190 }
191 }
192 if (fallbackToMeta && !foundMeta) {
193 return false;
194 }
195 }
196 }
197 return true;
198 }
199
200
201
202
203 protected boolean isQualifier(Class<? extends Annotation> annotationType) {
204 for (Class<? extends Annotation> qualifierType : this.qualifierTypes) {
205 if (annotationType.equals(qualifierType) || annotationType.isAnnotationPresent(qualifierType)) {
206 return true;
207 }
208 }
209 return false;
210 }
211
212
213
214
215 protected boolean checkQualifier(
216 BeanDefinitionHolder bdHolder, Annotation annotation, TypeConverter typeConverter) {
217
218 Class<? extends Annotation> type = annotation.annotationType();
219 RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
220
221 AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());
222 if (qualifier == null) {
223 qualifier = bd.getQualifier(ClassUtils.getShortName(type));
224 }
225 if (qualifier == null) {
226
227 Annotation targetAnnotation = getFactoryMethodAnnotation(bd, type);
228 if (targetAnnotation == null) {
229 RootBeanDefinition dbd = getResolvedDecoratedDefinition(bd);
230 if (dbd != null) {
231 targetAnnotation = getFactoryMethodAnnotation(dbd, type);
232 }
233 }
234 if (targetAnnotation == null) {
235
236 if (getBeanFactory() != null) {
237 try {
238 Class<?> beanType = getBeanFactory().getType(bdHolder.getBeanName());
239 if (beanType != null) {
240 targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(beanType), type);
241 }
242 }
243 catch (NoSuchBeanDefinitionException ex) {
244
245 }
246 }
247 if (targetAnnotation == null && bd.hasBeanClass()) {
248 targetAnnotation = AnnotationUtils.getAnnotation(ClassUtils.getUserClass(bd.getBeanClass()), type);
249 }
250 }
251 if (targetAnnotation != null && targetAnnotation.equals(annotation)) {
252 return true;
253 }
254 }
255
256 Map<String, Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation);
257 if (attributes.isEmpty() && qualifier == null) {
258
259 return false;
260 }
261 for (Map.Entry<String, Object> entry : attributes.entrySet()) {
262 String attributeName = entry.getKey();
263 Object expectedValue = entry.getValue();
264 Object actualValue = null;
265
266 if (qualifier != null) {
267 actualValue = qualifier.getAttribute(attributeName);
268 }
269 if (actualValue == null) {
270
271 actualValue = bd.getAttribute(attributeName);
272 }
273 if (actualValue == null && attributeName.equals(AutowireCandidateQualifier.VALUE_KEY) &&
274 expectedValue instanceof String && bdHolder.matchesName((String) expectedValue)) {
275
276 continue;
277 }
278 if (actualValue == null && qualifier != null) {
279
280 actualValue = AnnotationUtils.getDefaultValue(annotation, attributeName);
281 }
282 if (actualValue != null) {
283 actualValue = typeConverter.convertIfNecessary(actualValue, expectedValue.getClass());
284 }
285 if (!expectedValue.equals(actualValue)) {
286 return false;
287 }
288 }
289 return true;
290 }
291
292 protected Annotation getFactoryMethodAnnotation(RootBeanDefinition bd, Class<? extends Annotation> type) {
293 Method resolvedFactoryMethod = bd.getResolvedFactoryMethod();
294 return (resolvedFactoryMethod != null ? AnnotationUtils.getAnnotation(resolvedFactoryMethod, type) : null);
295 }
296
297
298
299
300
301
302 @Override
303 public Object getSuggestedValue(DependencyDescriptor descriptor) {
304 Object value = findValue(descriptor.getAnnotations());
305 if (value == null) {
306 MethodParameter methodParam = descriptor.getMethodParameter();
307 if (methodParam != null) {
308 value = findValue(methodParam.getMethodAnnotations());
309 }
310 }
311 return value;
312 }
313
314
315
316
317 protected Object findValue(Annotation[] annotationsToSearch) {
318 for (Annotation annotation : annotationsToSearch) {
319 if (this.valueAnnotationType.isInstance(annotation)) {
320 return extractValue(annotation);
321 }
322 }
323 for (Annotation annotation : annotationsToSearch) {
324 Annotation metaAnn = annotation.annotationType().getAnnotation(this.valueAnnotationType);
325 if (metaAnn != null) {
326 return extractValue(metaAnn);
327 }
328 }
329 return null;
330 }
331
332
333
334
335 protected Object extractValue(Annotation valueAnnotation) {
336 Object value = AnnotationUtils.getValue(valueAnnotation);
337 if (value == null) {
338 throw new IllegalStateException("Value annotation must have a value attribute");
339 }
340 return value;
341 }
342
343 }