Source Code Cross Referenced for ConstructorResolver.java in  » J2EE » spring-framework-2.0.6 » org » springframework » beans » factory » support » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.0.6 » org.springframework.beans.factory.support 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.beans.factory.support;
018:
019:        import java.lang.reflect.Constructor;
020:        import java.lang.reflect.Method;
021:        import java.lang.reflect.Modifier;
022:        import java.util.HashSet;
023:        import java.util.Iterator;
024:        import java.util.Map;
025:        import java.util.Set;
026:
027:        import org.springframework.beans.BeanMetadataElement;
028:        import org.springframework.beans.BeanWrapper;
029:        import org.springframework.beans.BeanWrapperImpl;
030:        import org.springframework.beans.BeansException;
031:        import org.springframework.beans.TypeMismatchException;
032:        import org.springframework.beans.factory.BeanCreationException;
033:        import org.springframework.beans.factory.BeanDefinitionStoreException;
034:        import org.springframework.beans.factory.UnsatisfiedDependencyException;
035:        import org.springframework.beans.factory.config.ConstructorArgumentValues;
036:        import org.springframework.beans.factory.config.TypedStringValue;
037:        import org.springframework.core.MethodParameter;
038:        import org.springframework.util.ObjectUtils;
039:        import org.springframework.util.ReflectionUtils;
040:
041:        /**
042:         * Helper class for resolving constructors and factory methods.
043:         * Performs constructor resolution through argument matching.
044:         *
045:         * <p>Operates on an {@link AbstractBeanFactory} and an {@link InstantiationStrategy}.
046:         * Used by {@link AbstractAutowireCapableBeanFactory}.
047:         *
048:         * @author Juergen Hoeller
049:         * @author Rob Harrop
050:         * @since 2.0
051:         * @see #autowireConstructor
052:         * @see #instantiateUsingFactoryMethod
053:         * @see AbstractAutowireCapableBeanFactory
054:         */
055:        abstract class ConstructorResolver {
056:
057:            private final AbstractBeanFactory beanFactory;
058:
059:            private final InstantiationStrategy instantiationStrategy;
060:
061:            /**
062:             * Create a new ConstructorResolver for the given factory and instantiation strategy.
063:             * @param beanFactory the BeanFactory to work with
064:             * @param instantiationStrategy the instantiate strategy for creating bean instances
065:             */
066:            public ConstructorResolver(AbstractBeanFactory beanFactory,
067:                    InstantiationStrategy instantiationStrategy) {
068:                this .beanFactory = beanFactory;
069:                this .instantiationStrategy = instantiationStrategy;
070:            }
071:
072:            /**
073:             * "autowire constructor" (with constructor arguments by type) behavior.
074:             * Also applied if explicit constructor argument values are specified,
075:             * matching all remaining arguments with beans from the bean factory.
076:             * <p>This corresponds to constructor injection: In this mode, a Spring
077:             * bean factory is able to host components that expect constructor-based
078:             * dependency resolution.
079:             * @param beanName the name of the bean
080:             * @param mbd the merged bean definition for the bean
081:             * @param chosenCtor a pre-chosen Constructor (or <code>null</code> if none)
082:             * @return a BeanWrapper for the new instance
083:             */
084:            protected BeanWrapper autowireConstructor(String beanName,
085:                    RootBeanDefinition mbd, Constructor chosenCtor) {
086:                BeanWrapper bw = new BeanWrapperImpl();
087:                this .beanFactory.initBeanWrapper(bw);
088:
089:                Constructor constructorToUse = (Constructor) mbd.resolvedConstructorOrFactoryMethod;
090:                Object[] argsToUse = null;
091:
092:                if (constructorToUse != null) {
093:                    // Found a cached constructor...
094:                    argsToUse = mbd.resolvedConstructorArguments;
095:                    if (argsToUse == null) {
096:                        Class[] paramTypes = constructorToUse
097:                                .getParameterTypes();
098:                        Object[] argsToResolve = mbd.preparedConstructorArguments;
099:                        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(
100:                                this .beanFactory, beanName, mbd, bw);
101:                        argsToUse = new Object[argsToResolve.length];
102:                        for (int i = 0; i < argsToResolve.length; i++) {
103:                            Object argValue = argsToResolve[i];
104:                            if (argValue instanceof  BeanMetadataElement) {
105:                                String argName = "constructor argument with index "
106:                                        + i;
107:                                argValue = valueResolver
108:                                        .resolveValueIfNecessary(argName,
109:                                                argValue);
110:                            }
111:                            argsToUse[i] = bw.convertIfNecessary(argValue,
112:                                    paramTypes[i], new MethodParameter(
113:                                            constructorToUse, i));
114:                        }
115:                    }
116:                }
117:
118:                else {
119:                    // Need to resolve the constructor.
120:                    boolean autowiring = (chosenCtor != null || mbd
121:                            .getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
122:
123:                    ConstructorArgumentValues cargs = mbd
124:                            .getConstructorArgumentValues();
125:                    ConstructorArgumentValues resolvedValues = new ConstructorArgumentValues();
126:                    int minNrOfArgs = resolveConstructorArguments(beanName,
127:                            mbd, bw, cargs, resolvedValues);
128:
129:                    // Take specified constructor, if any.
130:                    if (chosenCtor != null) {
131:                        Class[] paramTypes = chosenCtor.getParameterTypes();
132:                        argsToUse = createArgumentArray(beanName, mbd,
133:                                resolvedValues, bw, paramTypes, chosenCtor,
134:                                autowiring).arguments;
135:                        constructorToUse = chosenCtor;
136:                    }
137:
138:                    else {
139:                        Constructor[] candidates = mbd.getBeanClass()
140:                                .getDeclaredConstructors();
141:                        AutowireUtils.sortConstructors(candidates);
142:                        int minTypeDiffWeight = Integer.MAX_VALUE;
143:
144:                        for (int i = 0; i < candidates.length; i++) {
145:                            Constructor candidate = candidates[i];
146:                            Class[] paramTypes = candidate.getParameterTypes();
147:
148:                            if (constructorToUse != null
149:                                    && argsToUse.length > paramTypes.length) {
150:                                // Already found greedy constructor that can be satisfied ->
151:                                // do not look any further, there are only less greedy constructors left.
152:                                break;
153:                            }
154:                            if (paramTypes.length < minNrOfArgs) {
155:                                throw new BeanCreationException(
156:                                        mbd.getResourceDescription(),
157:                                        beanName,
158:                                        minNrOfArgs
159:                                                + " constructor arguments specified but no matching constructor found in bean '"
160:                                                + beanName
161:                                                + "' "
162:                                                + "(hint: specify index and/or type arguments for simple parameters to avoid type ambiguities)");
163:                            }
164:
165:                            // Try to resolve arguments for current constructor.
166:                            try {
167:                                ArgumentsHolder args = createArgumentArray(
168:                                        beanName, mbd, resolvedValues, bw,
169:                                        paramTypes, candidate, autowiring);
170:                                int typeDiffWeight = args
171:                                        .getTypeDifferenceWeight(paramTypes);
172:                                // Choose this constructor if it represents the closest match.
173:                                if (typeDiffWeight < minTypeDiffWeight) {
174:                                    constructorToUse = candidate;
175:                                    argsToUse = args.arguments;
176:                                    minTypeDiffWeight = typeDiffWeight;
177:                                }
178:                            } catch (UnsatisfiedDependencyException ex) {
179:                                if (this .beanFactory.logger.isTraceEnabled()) {
180:                                    this .beanFactory.logger
181:                                            .trace("Ignoring constructor ["
182:                                                    + candidate + "] of bean '"
183:                                                    + beanName + "': " + ex);
184:                                }
185:                                if (i == candidates.length - 1
186:                                        && constructorToUse == null) {
187:                                    throw ex;
188:                                } else {
189:                                    // Swallow and try next constructor.
190:                                }
191:                            }
192:                        }
193:
194:                        if (constructorToUse == null) {
195:                            throw new BeanCreationException(mbd
196:                                    .getResourceDescription(), beanName,
197:                                    "Could not resolve matching constructor");
198:                        }
199:                    }
200:
201:                    mbd.resolvedConstructorOrFactoryMethod = constructorToUse;
202:                }
203:
204:                Object beanInstance = this .instantiationStrategy.instantiate(
205:                        mbd, beanName, this .beanFactory, constructorToUse,
206:                        argsToUse);
207:                bw.setWrappedInstance(beanInstance);
208:                return bw;
209:            }
210:
211:            /**
212:             * Instantiate the bean using a named factory method. The method may be static, if the
213:             * bean definition parameter specifies a class, rather than a "factory-bean", or
214:             * an instance variable on a factory object itself configured using Dependency Injection.
215:             * <p>Implementation requires iterating over the static or instance methods with the
216:             * name specified in the RootBeanDefinition (the method may be overloaded) and trying
217:             * to match with the parameters. We don't have the types attached to constructor args,
218:             * so trial and error is the only way to go here. The explicitArgs array may contain
219:             * argument values passed in programmatically via the corresponding getBean method.
220:             * @param beanName the name of the bean
221:             * @param mbd the merged bean definition for the bean
222:             * @param explicitArgs argument values passed in programmatically via the getBean
223:             * method, or <code>null</code> if none (-> use constructor argument values from bean definition)
224:             * @return a BeanWrapper for the new instance
225:             */
226:            public BeanWrapper instantiateUsingFactoryMethod(String beanName,
227:                    RootBeanDefinition mbd, Object[] explicitArgs) {
228:                BeanWrapper bw = new BeanWrapperImpl();
229:                this .beanFactory.initBeanWrapper(bw);
230:
231:                Class factoryClass = null;
232:                Object factoryBean = null;
233:                boolean isStatic = true;
234:
235:                if (mbd.getFactoryBeanName() != null) {
236:                    factoryBean = this .beanFactory.getBean(mbd
237:                            .getFactoryBeanName());
238:                    factoryClass = factoryBean.getClass();
239:                    isStatic = false;
240:                } else {
241:                    // It's a static factory method on the bean class.
242:                    factoryClass = mbd.getBeanClass();
243:                }
244:
245:                Method factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
246:                Object[] argsToUse = null;
247:
248:                if (factoryMethodToUse != null) {
249:                    // Found a cached factory method...
250:                    if (explicitArgs != null) {
251:                        argsToUse = explicitArgs;
252:                    } else {
253:                        argsToUse = mbd.resolvedConstructorArguments;
254:                        if (argsToUse == null) {
255:                            Class[] paramTypes = factoryMethodToUse
256:                                    .getParameterTypes();
257:                            Object[] argsToResolve = mbd.preparedConstructorArguments;
258:                            BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(
259:                                    this .beanFactory, beanName, mbd, bw);
260:                            argsToUse = new Object[argsToResolve.length];
261:                            for (int i = 0; i < argsToResolve.length; i++) {
262:                                Object argValue = argsToResolve[i];
263:                                if (argValue instanceof  BeanMetadataElement) {
264:                                    String argName = "factory method argument with index "
265:                                            + i;
266:                                    argValue = valueResolver
267:                                            .resolveValueIfNecessary(argName,
268:                                                    argValue);
269:                                }
270:                                argsToUse[i] = bw.convertIfNecessary(argValue,
271:                                        paramTypes[i], new MethodParameter(
272:                                                factoryMethodToUse, i));
273:                            }
274:                        }
275:                    }
276:                }
277:
278:                else {
279:                    // Need to determine the factory method...
280:                    // Try all methods with this name to see if they match the given arguments.
281:                    Method[] candidates = ReflectionUtils
282:                            .getAllDeclaredMethods(factoryClass);
283:                    boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
284:                    int minTypeDiffWeight = Integer.MAX_VALUE;
285:                    ConstructorArgumentValues resolvedValues = null;
286:
287:                    int minNrOfArgs = 0;
288:                    if (explicitArgs != null) {
289:                        minNrOfArgs = explicitArgs.length;
290:                    } else {
291:                        // We don't have arguments passed in programmatically, so we need to resolve the
292:                        // arguments specified in the constructor arguments held in the bean definition.
293:                        ConstructorArgumentValues cargs = mbd
294:                                .getConstructorArgumentValues();
295:                        resolvedValues = new ConstructorArgumentValues();
296:                        minNrOfArgs = resolveConstructorArguments(beanName,
297:                                mbd, bw, cargs, resolvedValues);
298:                    }
299:
300:                    for (int i = 0; i < candidates.length; i++) {
301:                        Method candidate = candidates[i];
302:                        Class[] paramTypes = candidate.getParameterTypes();
303:
304:                        if (Modifier.isStatic(candidate.getModifiers()) == isStatic
305:                                && candidate.getName().equals(
306:                                        mbd.getFactoryMethodName())
307:                                && paramTypes.length >= minNrOfArgs) {
308:
309:                            ArgumentsHolder args = null;
310:
311:                            if (resolvedValues != null) {
312:                                // Resolved contructor arguments: type conversion and/or autowiring necessary.
313:                                try {
314:                                    args = createArgumentArray(beanName, mbd,
315:                                            resolvedValues, bw, paramTypes,
316:                                            candidate, autowiring);
317:                                } catch (UnsatisfiedDependencyException ex) {
318:                                    if (this .beanFactory.logger
319:                                            .isTraceEnabled()) {
320:                                        this .beanFactory.logger
321:                                                .trace("Ignoring factory method ["
322:                                                        + candidate
323:                                                        + "] of bean '"
324:                                                        + beanName + "': " + ex);
325:                                    }
326:                                    if (i == candidates.length - 1
327:                                            && factoryMethodToUse == null) {
328:                                        throw ex;
329:                                    } else {
330:                                        // Swallow and try next overloaded factory method.
331:                                        continue;
332:                                    }
333:                                }
334:                            }
335:
336:                            else {
337:                                // Explicit arguments given -> arguments length must match exactly.
338:                                if (paramTypes.length != explicitArgs.length) {
339:                                    continue;
340:                                }
341:                                args = new ArgumentsHolder(explicitArgs);
342:                            }
343:
344:                            int typeDiffWeight = args
345:                                    .getTypeDifferenceWeight(paramTypes);
346:                            // Choose this constructor if it represents the closest match.
347:                            if (typeDiffWeight < minTypeDiffWeight) {
348:                                factoryMethodToUse = candidate;
349:                                argsToUse = args.arguments;
350:                                minTypeDiffWeight = typeDiffWeight;
351:                            }
352:                        }
353:                    }
354:
355:                    if (factoryMethodToUse == null) {
356:                        throw new BeanDefinitionStoreException(
357:                                "No matching factory method found: "
358:                                        + (mbd.getFactoryBeanName() != null ? "factory bean '"
359:                                                + mbd.getFactoryBeanName()
360:                                                + "'; "
361:                                                : "") + "factory method '"
362:                                        + mbd.getFactoryMethodName() + "'");
363:                    }
364:                    mbd.resolvedConstructorOrFactoryMethod = factoryMethodToUse;
365:                }
366:
367:                Object beanInstance = this .instantiationStrategy.instantiate(
368:                        mbd, beanName, this .beanFactory, factoryBean,
369:                        factoryMethodToUse, argsToUse);
370:                if (beanInstance == null) {
371:                    return null;
372:                }
373:
374:                bw.setWrappedInstance(beanInstance);
375:                return bw;
376:            }
377:
378:            /**
379:             * Resolve the constructor arguments for this bean into the resolvedValues object.
380:             * This may involve looking up other beans.
381:             * This method is also used for handling invocations of static factory methods.
382:             */
383:            private int resolveConstructorArguments(String beanName,
384:                    RootBeanDefinition mbd, BeanWrapper bw,
385:                    ConstructorArgumentValues cargs,
386:                    ConstructorArgumentValues resolvedValues) {
387:
388:                BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(
389:                        this .beanFactory, beanName, mbd, bw);
390:
391:                int minNrOfArgs = cargs.getArgumentCount();
392:
393:                for (Iterator it = cargs.getIndexedArgumentValues().entrySet()
394:                        .iterator(); it.hasNext();) {
395:                    Map.Entry entry = (Map.Entry) it.next();
396:                    int index = ((Integer) entry.getKey()).intValue();
397:                    if (index < 0) {
398:                        throw new BeanCreationException(mbd
399:                                .getResourceDescription(), beanName,
400:                                "Invalid constructor argument index: " + index);
401:                    }
402:                    if (index > minNrOfArgs) {
403:                        minNrOfArgs = index + 1;
404:                    }
405:                    ConstructorArgumentValues.ValueHolder valueHolder = (ConstructorArgumentValues.ValueHolder) entry
406:                            .getValue();
407:                    if (valueHolder.isConverted()) {
408:                        resolvedValues.addIndexedArgumentValue(index,
409:                                valueHolder);
410:                    } else {
411:                        String argName = "constructor argument with index "
412:                                + index;
413:                        Object resolvedValue = valueResolver
414:                                .resolveValueIfNecessary(argName, valueHolder
415:                                        .getValue());
416:                        ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
417:                                resolvedValue, valueHolder.getType());
418:                        resolvedValueHolder.setSource(valueHolder);
419:                        resolvedValues.addIndexedArgumentValue(index,
420:                                resolvedValueHolder);
421:                    }
422:                }
423:
424:                for (Iterator it = cargs.getGenericArgumentValues().iterator(); it
425:                        .hasNext();) {
426:                    ConstructorArgumentValues.ValueHolder valueHolder = (ConstructorArgumentValues.ValueHolder) it
427:                            .next();
428:                    if (valueHolder.isConverted()) {
429:                        resolvedValues.addGenericArgumentValue(valueHolder);
430:                    } else {
431:                        String argName = "constructor argument";
432:                        Object resolvedValue = valueResolver
433:                                .resolveValueIfNecessary(argName, valueHolder
434:                                        .getValue());
435:                        ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(
436:                                resolvedValue, valueHolder.getType());
437:                        resolvedValueHolder.setSource(valueHolder);
438:                        resolvedValues
439:                                .addGenericArgumentValue(resolvedValueHolder);
440:                    }
441:                }
442:
443:                return minNrOfArgs;
444:            }
445:
446:            /**
447:             * Create an array of arguments to invoke a constructor or factory method,
448:             * given the resolved constructor argument values.
449:             */
450:            private ArgumentsHolder createArgumentArray(String beanName,
451:                    RootBeanDefinition mbd,
452:                    ConstructorArgumentValues resolvedValues, BeanWrapper bw,
453:                    Class[] paramTypes, Object methodOrCtor, boolean autowiring)
454:                    throws UnsatisfiedDependencyException {
455:
456:                String methodType = (methodOrCtor instanceof  Constructor ? "constructor"
457:                        : "factory method");
458:
459:                ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
460:                Set usedValueHolders = new HashSet(paramTypes.length);
461:                boolean resolveNecessary = false;
462:
463:                for (int index = 0; index < paramTypes.length; index++) {
464:                    // Try to find matching constructor argument value, either indexed or generic.
465:                    ConstructorArgumentValues.ValueHolder valueHolder = resolvedValues
466:                            .getArgumentValue(index, paramTypes[index],
467:                                    usedValueHolders);
468:                    // If we couldn't find a direct match and are not supposed to autowire,
469:                    // let's try the next generic, untyped argument value as fallback:
470:                    // it could match after type conversion (for example, String -> int).
471:                    if (valueHolder == null && !autowiring) {
472:                        valueHolder = resolvedValues.getGenericArgumentValue(
473:                                null, usedValueHolders);
474:                    }
475:                    if (valueHolder != null) {
476:                        // We found a potential match - let's give it a try.
477:                        // Do not consider the same value definition multiple times!
478:                        usedValueHolders.add(valueHolder);
479:                        args.rawArguments[index] = valueHolder.getValue();
480:                        if (valueHolder.isConverted()) {
481:                            Object convertedValue = valueHolder
482:                                    .getConvertedValue();
483:                            args.arguments[index] = convertedValue;
484:                            args.preparedArguments[index] = convertedValue;
485:                        } else {
486:                            try {
487:                                Object originalValue = valueHolder.getValue();
488:                                Object convertedValue = bw.convertIfNecessary(
489:                                        originalValue, paramTypes[index],
490:                                        MethodParameter.forMethodOrConstructor(
491:                                                methodOrCtor, index));
492:                                args.arguments[index] = convertedValue;
493:                                ConstructorArgumentValues.ValueHolder sourceHolder = (ConstructorArgumentValues.ValueHolder) valueHolder
494:                                        .getSource();
495:                                Object sourceValue = sourceHolder.getValue();
496:                                if (originalValue == sourceValue
497:                                        || sourceValue instanceof  TypedStringValue) {
498:                                    // Either a converted value or still the original one: store converted value.
499:                                    sourceHolder
500:                                            .setConvertedValue(convertedValue);
501:                                    args.preparedArguments[index] = convertedValue;
502:                                } else {
503:                                    resolveNecessary = true;
504:                                    args.preparedArguments[index] = sourceValue;
505:                                }
506:                            } catch (TypeMismatchException ex) {
507:                                throw new UnsatisfiedDependencyException(
508:                                        mbd.getResourceDescription(),
509:                                        beanName,
510:                                        index,
511:                                        paramTypes[index],
512:                                        "Could not convert "
513:                                                + methodType
514:                                                + " argument value of type ["
515:                                                + ObjectUtils
516:                                                        .nullSafeClassName(valueHolder
517:                                                                .getValue())
518:                                                + "] to required type ["
519:                                                + paramTypes[index].getName()
520:                                                + "]: " + ex.getMessage());
521:                            }
522:                        }
523:                    } else {
524:                        // No explicit match found: we're either supposed to autowire or
525:                        // have to fail creating an argument array for the given constructor.
526:                        if (!autowiring) {
527:                            throw new UnsatisfiedDependencyException(
528:                                    mbd.getResourceDescription(),
529:                                    beanName,
530:                                    index,
531:                                    paramTypes[index],
532:                                    "Ambiguous "
533:                                            + methodType
534:                                            + " argument types - "
535:                                            + "did you specify the correct bean references as "
536:                                            + methodType + " arguments?");
537:                        }
538:                        Map matchingBeans = findAutowireCandidates(beanName,
539:                                paramTypes[index]);
540:                        if (matchingBeans.size() != 1) {
541:                            throw new UnsatisfiedDependencyException(
542:                                    mbd.getResourceDescription(),
543:                                    beanName,
544:                                    index,
545:                                    paramTypes[index],
546:                                    "There are "
547:                                            + matchingBeans.size()
548:                                            + " beans of type ["
549:                                            + paramTypes[index].getName()
550:                                            + "] available for autowiring: "
551:                                            + matchingBeans.keySet()
552:                                            + ". There should have been exactly 1 to be able to autowire "
553:                                            + methodType + " of bean '"
554:                                            + beanName + "'.");
555:                        }
556:                        Map.Entry entry = (Map.Entry) matchingBeans.entrySet()
557:                                .iterator().next();
558:                        String autowiredBeanName = (String) entry.getKey();
559:                        Object autowiredBean = entry.getValue();
560:                        args.rawArguments[index] = autowiredBean;
561:                        args.arguments[index] = autowiredBean;
562:                        if (mbd.isSingleton()) {
563:                            this .beanFactory.registerDependentBean(
564:                                    autowiredBeanName, beanName);
565:                        }
566:                        if (this .beanFactory.logger.isDebugEnabled()) {
567:                            this .beanFactory.logger
568:                                    .debug("Autowiring by type from bean name '"
569:                                            + beanName
570:                                            + "' via "
571:                                            + methodType
572:                                            + " to bean named '"
573:                                            + autowiredBeanName + "'");
574:                        }
575:                    }
576:                }
577:
578:                if (resolveNecessary) {
579:                    mbd.preparedConstructorArguments = args.preparedArguments;
580:                } else {
581:                    mbd.resolvedConstructorArguments = args.arguments;
582:                }
583:                return args;
584:            }
585:
586:            /**
587:             * Find bean instances that match the required type.
588:             * Called during autowiring for the specified bean.
589:             * <p>If a subclass cannot obtain information about bean names by type,
590:             * a corresponding exception should be thrown.
591:             * @param beanName the name of the bean that is about to be wired
592:             * @param requiredType the type of the autowired constructor argument
593:             * @return a Map of candidate names and candidate instances that match
594:             * the required type (never <code>null</code>)
595:             * @throws BeansException in case of errors
596:             * @see #autowireConstructor
597:             */
598:            protected abstract Map findAutowireCandidates(String beanName,
599:                    Class requiredType) throws BeansException;
600:
601:            /**
602:             * Private inner class for holding argument combinations.
603:             */
604:            private static class ArgumentsHolder {
605:
606:                public Object rawArguments[];
607:
608:                public Object arguments[];
609:
610:                public Object preparedArguments[];
611:
612:                public ArgumentsHolder(int size) {
613:                    this .rawArguments = new Object[size];
614:                    this .arguments = new Object[size];
615:                    this .preparedArguments = new Object[size];
616:                }
617:
618:                public ArgumentsHolder(Object[] args) {
619:                    this .rawArguments = args;
620:                    this .arguments = args;
621:                    this .preparedArguments = args;
622:                }
623:
624:                public int getTypeDifferenceWeight(Class[] paramTypes) {
625:                    // If valid arguments found, determine type difference weight.
626:                    // Try type difference weight on both the converted arguments and
627:                    // the raw arguments. If the raw weight is better, use it.
628:                    // Decrease raw weight by 1024 to prefer it over equal converted weight.
629:                    int typeDiffWeight = AutowireUtils.getTypeDifferenceWeight(
630:                            paramTypes, this .arguments);
631:                    int rawTypeDiffWeight = AutowireUtils
632:                            .getTypeDifferenceWeight(paramTypes,
633:                                    this .rawArguments) - 1024;
634:                    return (rawTypeDiffWeight < typeDiffWeight ? rawTypeDiffWeight
635:                            : typeDiffWeight);
636:                }
637:            }
638:
639:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.