1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.beans.factory.support;
18
19 import java.beans.ConstructorProperties;
20 import java.lang.reflect.Constructor;
21 import java.lang.reflect.Member;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Modifier;
24 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.HashSet;
29 import java.util.LinkedHashSet;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34
35 import org.springframework.beans.BeanMetadataElement;
36 import org.springframework.beans.BeanWrapper;
37 import org.springframework.beans.BeanWrapperImpl;
38 import org.springframework.beans.BeansException;
39 import org.springframework.beans.TypeConverter;
40 import org.springframework.beans.TypeMismatchException;
41 import org.springframework.beans.factory.BeanCreationException;
42 import org.springframework.beans.factory.BeanDefinitionStoreException;
43 import org.springframework.beans.factory.UnsatisfiedDependencyException;
44 import org.springframework.beans.factory.config.ConstructorArgumentValues;
45 import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
46 import org.springframework.beans.factory.config.DependencyDescriptor;
47 import org.springframework.core.GenericTypeResolver;
48 import org.springframework.core.MethodParameter;
49 import org.springframework.core.ParameterNameDiscoverer;
50 import org.springframework.util.ClassUtils;
51 import org.springframework.util.MethodInvoker;
52 import org.springframework.util.ObjectUtils;
53 import org.springframework.util.ReflectionUtils;
54 import org.springframework.util.StringUtils;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 class ConstructorResolver {
70
71 private final AbstractAutowireCapableBeanFactory beanFactory;
72
73
74
75
76
77
78 public ConstructorResolver(AbstractAutowireCapableBeanFactory beanFactory) {
79 this.beanFactory = beanFactory;
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
98 Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
99
100 BeanWrapperImpl bw = new BeanWrapperImpl();
101 this.beanFactory.initBeanWrapper(bw);
102
103 Constructor<?> constructorToUse = null;
104 ArgumentsHolder argsHolderToUse = null;
105 Object[] argsToUse = null;
106
107 if (explicitArgs != null) {
108 argsToUse = explicitArgs;
109 }
110 else {
111 Object[] argsToResolve = null;
112 synchronized (mbd.constructorArgumentLock) {
113 constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
114 if (constructorToUse != null && mbd.constructorArgumentsResolved) {
115
116 argsToUse = mbd.resolvedConstructorArguments;
117 if (argsToUse == null) {
118 argsToResolve = mbd.preparedConstructorArguments;
119 }
120 }
121 }
122 if (argsToResolve != null) {
123 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
124 }
125 }
126
127 if (constructorToUse == null) {
128
129 boolean autowiring = (chosenCtors != null ||
130 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
131 ConstructorArgumentValues resolvedValues = null;
132
133 int minNrOfArgs;
134 if (explicitArgs != null) {
135 minNrOfArgs = explicitArgs.length;
136 }
137 else {
138 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
139 resolvedValues = new ConstructorArgumentValues();
140 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
141 }
142
143
144 Constructor<?>[] candidates = chosenCtors;
145 if (candidates == null) {
146 Class<?> beanClass = mbd.getBeanClass();
147 try {
148 candidates = (mbd.isNonPublicAccessAllowed() ?
149 beanClass.getDeclaredConstructors() : beanClass.getConstructors());
150 }
151 catch (Throwable ex) {
152 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
153 "Resolution of declared constructors on bean Class [" + beanClass.getName() +
154 "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
155 }
156 }
157 AutowireUtils.sortConstructors(candidates);
158 int minTypeDiffWeight = Integer.MAX_VALUE;
159 Set<Constructor<?>> ambiguousConstructors = null;
160 LinkedList<UnsatisfiedDependencyException> causes = null;
161
162 for (int i = 0; i < candidates.length; i++) {
163 Constructor<?> candidate = candidates[i];
164 Class<?>[] paramTypes = candidate.getParameterTypes();
165
166 if (constructorToUse != null && argsToUse.length > paramTypes.length) {
167
168
169 break;
170 }
171 if (paramTypes.length < minNrOfArgs) {
172 continue;
173 }
174
175 ArgumentsHolder argsHolder;
176 if (resolvedValues != null) {
177 try {
178 String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
179 if (paramNames == null) {
180 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
181 if (pnd != null) {
182 paramNames = pnd.getParameterNames(candidate);
183 }
184 }
185 argsHolder = createArgumentArray(
186 beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
187 }
188 catch (UnsatisfiedDependencyException ex) {
189 if (this.beanFactory.logger.isTraceEnabled()) {
190 this.beanFactory.logger.trace(
191 "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
192 }
193
194 if (causes == null) {
195 causes = new LinkedList<UnsatisfiedDependencyException>();
196 }
197 causes.add(ex);
198 continue;
199 }
200 }
201 else {
202
203 if (paramTypes.length != explicitArgs.length) {
204 continue;
205 }
206 argsHolder = new ArgumentsHolder(explicitArgs);
207 }
208
209 int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
210 argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
211
212 if (typeDiffWeight < minTypeDiffWeight) {
213 constructorToUse = candidate;
214 argsHolderToUse = argsHolder;
215 argsToUse = argsHolder.arguments;
216 minTypeDiffWeight = typeDiffWeight;
217 ambiguousConstructors = null;
218 }
219 else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
220 if (ambiguousConstructors == null) {
221 ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
222 ambiguousConstructors.add(constructorToUse);
223 }
224 ambiguousConstructors.add(candidate);
225 }
226 }
227
228 if (constructorToUse == null) {
229 if (causes != null) {
230 UnsatisfiedDependencyException ex = causes.removeLast();
231 for (Exception cause : causes) {
232 this.beanFactory.onSuppressedException(cause);
233 }
234 throw ex;
235 }
236 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
237 "Could not resolve matching constructor " +
238 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
239 }
240 else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
241 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
242 "Ambiguous constructor matches found in bean '" + beanName + "' " +
243 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
244 ambiguousConstructors);
245 }
246
247 if (explicitArgs == null) {
248 argsHolderToUse.storeCache(mbd, constructorToUse);
249 }
250 }
251
252 try {
253 Object beanInstance;
254
255 if (System.getSecurityManager() != null) {
256 final Constructor<?> ctorToUse = constructorToUse;
257 final Object[] argumentsToUse = argsToUse;
258 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
259 @Override
260 public Object run() {
261 return beanFactory.getInstantiationStrategy().instantiate(
262 mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
263 }
264 }, beanFactory.getAccessControlContext());
265 }
266 else {
267 beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
268 mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
269 }
270
271 bw.setWrappedInstance(beanInstance);
272 return bw;
273 }
274 catch (Throwable ex) {
275 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
276 "Bean instantiation via constructor failed", ex);
277 }
278 }
279
280
281
282
283
284
285 public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
286 Class<?> factoryClass;
287 boolean isStatic;
288 if (mbd.getFactoryBeanName() != null) {
289 factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
290 isStatic = false;
291 }
292 else {
293 factoryClass = mbd.getBeanClass();
294 isStatic = true;
295 }
296 factoryClass = ClassUtils.getUserClass(factoryClass);
297
298 Method[] candidates = getCandidateMethods(factoryClass, mbd);
299 Method uniqueCandidate = null;
300 for (Method candidate : candidates) {
301 if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
302 if (uniqueCandidate == null) {
303 uniqueCandidate = candidate;
304 }
305 else if (!Arrays.equals(uniqueCandidate.getParameterTypes(), candidate.getParameterTypes())) {
306 uniqueCandidate = null;
307 break;
308 }
309 }
310 }
311 synchronized (mbd.constructorArgumentLock) {
312 mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
313 }
314 }
315
316
317
318
319
320
321 private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
322 if (System.getSecurityManager() != null) {
323 return AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
324 @Override
325 public Method[] run() {
326 return (mbd.isNonPublicAccessAllowed() ?
327 ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
328 }
329 });
330 }
331 else {
332 return (mbd.isNonPublicAccessAllowed() ?
333 ReflectionUtils.getAllDeclaredMethods(factoryClass) : factoryClass.getMethods());
334 }
335 }
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 public BeanWrapper instantiateUsingFactoryMethod(
353 final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
354
355 BeanWrapperImpl bw = new BeanWrapperImpl();
356 this.beanFactory.initBeanWrapper(bw);
357
358 Object factoryBean;
359 Class<?> factoryClass;
360 boolean isStatic;
361
362 String factoryBeanName = mbd.getFactoryBeanName();
363 if (factoryBeanName != null) {
364 if (factoryBeanName.equals(beanName)) {
365 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
366 "factory-bean reference points back to the same bean definition");
367 }
368 factoryBean = this.beanFactory.getBean(factoryBeanName);
369 if (factoryBean == null) {
370 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
371 "factory-bean '" + factoryBeanName + "' (or a BeanPostProcessor involved) returned null");
372 }
373 if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
374 throw new IllegalStateException("About-to-be-created singleton instance implicitly appeared " +
375 "through the creation of the factory bean that its bean definition points to");
376 }
377 factoryClass = factoryBean.getClass();
378 isStatic = false;
379 }
380 else {
381
382 if (!mbd.hasBeanClass()) {
383 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
384 "bean definition declares neither a bean class nor a factory-bean reference");
385 }
386 factoryBean = null;
387 factoryClass = mbd.getBeanClass();
388 isStatic = true;
389 }
390
391 Method factoryMethodToUse = null;
392 ArgumentsHolder argsHolderToUse = null;
393 Object[] argsToUse = null;
394
395 if (explicitArgs != null) {
396 argsToUse = explicitArgs;
397 }
398 else {
399 Object[] argsToResolve = null;
400 synchronized (mbd.constructorArgumentLock) {
401 factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
402 if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
403
404 argsToUse = mbd.resolvedConstructorArguments;
405 if (argsToUse == null) {
406 argsToResolve = mbd.preparedConstructorArguments;
407 }
408 }
409 }
410 if (argsToResolve != null) {
411 argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
412 }
413 }
414
415 if (factoryMethodToUse == null || argsToUse == null) {
416
417
418 factoryClass = ClassUtils.getUserClass(factoryClass);
419
420 Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
421 List<Method> candidateSet = new ArrayList<Method>();
422 for (Method candidate : rawCandidates) {
423 if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
424 candidateSet.add(candidate);
425 }
426 }
427 Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
428 AutowireUtils.sortFactoryMethods(candidates);
429
430 ConstructorArgumentValues resolvedValues = null;
431 boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
432 int minTypeDiffWeight = Integer.MAX_VALUE;
433 Set<Method> ambiguousFactoryMethods = null;
434
435 int minNrOfArgs;
436 if (explicitArgs != null) {
437 minNrOfArgs = explicitArgs.length;
438 }
439 else {
440
441
442 ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
443 resolvedValues = new ConstructorArgumentValues();
444 minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
445 }
446
447 List<Exception> causes = null;
448
449 for (int i = 0; i < candidates.length; i++) {
450 Method candidate = candidates[i];
451 Class<?>[] paramTypes = candidate.getParameterTypes();
452
453 if (paramTypes.length >= minNrOfArgs) {
454 ArgumentsHolder argsHolder;
455
456 if (resolvedValues != null) {
457
458 try {
459 String[] paramNames = null;
460 ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
461 if (pnd != null) {
462 paramNames = pnd.getParameterNames(candidate);
463 }
464 argsHolder = createArgumentArray(
465 beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
466 }
467 catch (UnsatisfiedDependencyException ex) {
468 if (this.beanFactory.logger.isTraceEnabled()) {
469 this.beanFactory.logger.trace("Ignoring factory method [" + candidate +
470 "] of bean '" + beanName + "': " + ex);
471 }
472 if (i == candidates.length - 1 && argsHolderToUse == null) {
473 if (causes != null) {
474 for (Exception cause : causes) {
475 this.beanFactory.onSuppressedException(cause);
476 }
477 }
478 throw ex;
479 }
480 else {
481
482 if (causes == null) {
483 causes = new LinkedList<Exception>();
484 }
485 causes.add(ex);
486 continue;
487 }
488 }
489 }
490
491 else {
492
493 if (paramTypes.length != explicitArgs.length) {
494 continue;
495 }
496 argsHolder = new ArgumentsHolder(explicitArgs);
497 }
498
499 int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
500 argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
501
502 if (typeDiffWeight < minTypeDiffWeight) {
503 factoryMethodToUse = candidate;
504 argsHolderToUse = argsHolder;
505 argsToUse = argsHolder.arguments;
506 minTypeDiffWeight = typeDiffWeight;
507 ambiguousFactoryMethods = null;
508 }
509
510
511
512
513
514 else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
515 !mbd.isLenientConstructorResolution() &&
516 paramTypes.length == factoryMethodToUse.getParameterTypes().length &&
517 !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
518 if (ambiguousFactoryMethods == null) {
519 ambiguousFactoryMethods = new LinkedHashSet<Method>();
520 ambiguousFactoryMethods.add(factoryMethodToUse);
521 }
522 ambiguousFactoryMethods.add(candidate);
523 }
524 }
525 }
526
527 if (factoryMethodToUse == null) {
528 List<String> argTypes = new ArrayList<String>(minNrOfArgs);
529 if (explicitArgs != null) {
530 for (Object arg : explicitArgs) {
531 argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
532 }
533 }
534 else {
535 Set<ValueHolder> valueHolders = new LinkedHashSet<ValueHolder>(resolvedValues.getArgumentCount());
536 valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
537 valueHolders.addAll(resolvedValues.getGenericArgumentValues());
538 for (ValueHolder value : valueHolders) {
539 String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
540 (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
541 argTypes.add(argType);
542 }
543 }
544 String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
545 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
546 "No matching factory method found: " +
547 (mbd.getFactoryBeanName() != null ?
548 "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +
549 "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +
550 "Check that a method with the specified name " +
551 (minNrOfArgs > 0 ? "and arguments " : "") +
552 "exists and that it is " +
553 (isStatic ? "static" : "non-static") + ".");
554 }
555 else if (void.class.equals(factoryMethodToUse.getReturnType())) {
556 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
557 "Invalid factory method '" + mbd.getFactoryMethodName() +
558 "': needs to have a non-void return type!");
559 }
560 else if (ambiguousFactoryMethods != null) {
561 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
562 "Ambiguous factory method matches found in bean '" + beanName + "' " +
563 "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
564 ambiguousFactoryMethods);
565 }
566
567 if (explicitArgs == null && argsHolderToUse != null) {
568 argsHolderToUse.storeCache(mbd, factoryMethodToUse);
569 }
570 }
571
572 try {
573 Object beanInstance;
574
575 if (System.getSecurityManager() != null) {
576 final Object fb = factoryBean;
577 final Method factoryMethod = factoryMethodToUse;
578 final Object[] args = argsToUse;
579 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
580 @Override
581 public Object run() {
582 return beanFactory.getInstantiationStrategy().instantiate(
583 mbd, beanName, beanFactory, fb, factoryMethod, args);
584 }
585 }, beanFactory.getAccessControlContext());
586 }
587 else {
588 beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
589 mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
590 }
591
592 if (beanInstance == null) {
593 return null;
594 }
595 bw.setWrappedInstance(beanInstance);
596 return bw;
597 }
598 catch (Throwable ex) {
599 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
600 "Bean instantiation via factory method failed", ex);
601 }
602 }
603
604
605
606
607
608
609 private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
610 ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
611
612 TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
613 this.beanFactory.getCustomTypeConverter() : bw);
614 BeanDefinitionValueResolver valueResolver =
615 new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
616
617 int minNrOfArgs = cargs.getArgumentCount();
618
619 for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
620 int index = entry.getKey();
621 if (index < 0) {
622 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
623 "Invalid constructor argument index: " + index);
624 }
625 if (index > minNrOfArgs) {
626 minNrOfArgs = index + 1;
627 }
628 ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
629 if (valueHolder.isConverted()) {
630 resolvedValues.addIndexedArgumentValue(index, valueHolder);
631 }
632 else {
633 Object resolvedValue =
634 valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
635 ConstructorArgumentValues.ValueHolder resolvedValueHolder =
636 new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
637 resolvedValueHolder.setSource(valueHolder);
638 resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
639 }
640 }
641
642 for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
643 if (valueHolder.isConverted()) {
644 resolvedValues.addGenericArgumentValue(valueHolder);
645 }
646 else {
647 Object resolvedValue =
648 valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
649 ConstructorArgumentValues.ValueHolder resolvedValueHolder =
650 new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
651 resolvedValueHolder.setSource(valueHolder);
652 resolvedValues.addGenericArgumentValue(resolvedValueHolder);
653 }
654 }
655
656 return minNrOfArgs;
657 }
658
659
660
661
662
663 private ArgumentsHolder createArgumentArray(
664 String beanName, RootBeanDefinition mbd, ConstructorArgumentValues resolvedValues,
665 BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,
666 boolean autowiring) throws UnsatisfiedDependencyException {
667
668 String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
669 TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
670 this.beanFactory.getCustomTypeConverter() : bw);
671
672 ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
673 Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
674 new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
675 Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
676
677 for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
678 Class<?> paramType = paramTypes[paramIndex];
679 String paramName = (paramNames != null ? paramNames[paramIndex] : null);
680
681 ConstructorArgumentValues.ValueHolder valueHolder =
682 resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
683
684
685
686 if (valueHolder == null && !autowiring) {
687 valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
688 }
689 if (valueHolder != null) {
690
691
692 usedValueHolders.add(valueHolder);
693 Object originalValue = valueHolder.getValue();
694 Object convertedValue;
695 if (valueHolder.isConverted()) {
696 convertedValue = valueHolder.getConvertedValue();
697 args.preparedArguments[paramIndex] = convertedValue;
698 }
699 else {
700 ConstructorArgumentValues.ValueHolder sourceHolder =
701 (ConstructorArgumentValues.ValueHolder) valueHolder.getSource();
702 Object sourceValue = sourceHolder.getValue();
703 try {
704 convertedValue = converter.convertIfNecessary(originalValue, paramType,
705 MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex));
706
707
708
709
710
711
712
713
714
715 args.resolveNecessary = true;
716 args.preparedArguments[paramIndex] = sourceValue;
717
718 }
719 catch (TypeMismatchException ex) {
720 throw new UnsatisfiedDependencyException(
721 mbd.getResourceDescription(), beanName, paramIndex, paramType,
722 "Could not convert " + methodType + " argument value of type [" +
723 ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
724 "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
725 }
726 }
727 args.arguments[paramIndex] = convertedValue;
728 args.rawArguments[paramIndex] = originalValue;
729 }
730 else {
731
732
733 if (!autowiring) {
734 throw new UnsatisfiedDependencyException(
735 mbd.getResourceDescription(), beanName, paramIndex, paramType,
736 "Ambiguous " + methodType + " argument types - " +
737 "did you specify the correct bean references as " + methodType + " arguments?");
738 }
739 try {
740 MethodParameter param = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);
741 Object autowiredArgument = resolveAutowiredArgument(param, beanName, autowiredBeanNames, converter);
742 args.rawArguments[paramIndex] = autowiredArgument;
743 args.arguments[paramIndex] = autowiredArgument;
744 args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
745 args.resolveNecessary = true;
746 }
747 catch (BeansException ex) {
748 throw new UnsatisfiedDependencyException(
749 mbd.getResourceDescription(), beanName, paramIndex, paramType, ex);
750 }
751 }
752 }
753
754 for (String autowiredBeanName : autowiredBeanNames) {
755 this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
756 if (this.beanFactory.logger.isDebugEnabled()) {
757 this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName +
758 "' via " + methodType + " to bean named '" + autowiredBeanName + "'");
759 }
760 }
761
762 return args;
763 }
764
765
766
767
768 private Object[] resolvePreparedArguments(
769 String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
770
771 Class<?>[] paramTypes = (methodOrCtor instanceof Method ?
772 ((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes());
773 TypeConverter converter = (this.beanFactory.getCustomTypeConverter() != null ?
774 this.beanFactory.getCustomTypeConverter() : bw);
775 BeanDefinitionValueResolver valueResolver =
776 new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
777 Object[] resolvedArgs = new Object[argsToResolve.length];
778 for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
779 Object argValue = argsToResolve[argIndex];
780 MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, argIndex);
781 GenericTypeResolver.resolveParameterType(methodParam, methodOrCtor.getDeclaringClass());
782 if (argValue instanceof AutowiredArgumentMarker) {
783 argValue = resolveAutowiredArgument(methodParam, beanName, null, converter);
784 }
785 else if (argValue instanceof BeanMetadataElement) {
786 argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
787 }
788 else if (argValue instanceof String) {
789 argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
790 }
791 Class<?> paramType = paramTypes[argIndex];
792 try {
793 resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
794 }
795 catch (TypeMismatchException ex) {
796 String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
797 throw new UnsatisfiedDependencyException(
798 mbd.getResourceDescription(), beanName, argIndex, paramType,
799 "Could not convert " + methodType + " argument value of type [" +
800 ObjectUtils.nullSafeClassName(argValue) +
801 "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
802 }
803 }
804 return resolvedArgs;
805 }
806
807
808
809
810 protected Object resolveAutowiredArgument(
811 MethodParameter param, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) {
812
813 return this.beanFactory.resolveDependency(
814 new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
815 }
816
817
818
819
820
821 private static class ArgumentsHolder {
822
823 public final Object rawArguments[];
824
825 public final Object arguments[];
826
827 public final Object preparedArguments[];
828
829 public boolean resolveNecessary = false;
830
831 public ArgumentsHolder(int size) {
832 this.rawArguments = new Object[size];
833 this.arguments = new Object[size];
834 this.preparedArguments = new Object[size];
835 }
836
837 public ArgumentsHolder(Object[] args) {
838 this.rawArguments = args;
839 this.arguments = args;
840 this.preparedArguments = args;
841 }
842
843 public int getTypeDifferenceWeight(Class<?>[] paramTypes) {
844
845
846
847
848 int typeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.arguments);
849 int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
850 return (rawTypeDiffWeight < typeDiffWeight ? rawTypeDiffWeight : typeDiffWeight);
851 }
852
853 public int getAssignabilityWeight(Class<?>[] paramTypes) {
854 for (int i = 0; i < paramTypes.length; i++) {
855 if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
856 return Integer.MAX_VALUE;
857 }
858 }
859 for (int i = 0; i < paramTypes.length; i++) {
860 if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
861 return Integer.MAX_VALUE - 512;
862 }
863 }
864 return Integer.MAX_VALUE - 1024;
865 }
866
867 public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) {
868 synchronized (mbd.constructorArgumentLock) {
869 mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
870 mbd.constructorArgumentsResolved = true;
871 if (this.resolveNecessary) {
872 mbd.preparedConstructorArguments = this.preparedArguments;
873 }
874 else {
875 mbd.resolvedConstructorArguments = this.arguments;
876 }
877 }
878 }
879 }
880
881
882
883
884
885 private static class AutowiredArgumentMarker {
886 }
887
888
889
890
891
892 private static class ConstructorPropertiesChecker {
893
894 public static String[] evaluate(Constructor<?> candidate, int paramCount) {
895 ConstructorProperties cp = candidate.getAnnotation(ConstructorProperties.class);
896 if (cp != null) {
897 String[] names = cp.value();
898 if (names.length != paramCount) {
899 throw new IllegalStateException("Constructor annotated with @ConstructorProperties but not " +
900 "corresponding to actual number of parameters (" + paramCount + "): " + candidate);
901 }
902 return names;
903 }
904 else {
905 return null;
906 }
907 }
908 }
909
910 }