KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > beans > factory > support > AbstractAutowireCapableBeanFactory


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.beans.factory.support;
18
19 import java.beans.PropertyDescriptor JavaDoc;
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.lang.reflect.Modifier JavaDoc;
23 import java.util.Arrays JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32 import java.util.TreeSet JavaDoc;
33
34 import org.springframework.beans.BeanUtils;
35 import org.springframework.beans.BeanWrapper;
36 import org.springframework.beans.BeanWrapperImpl;
37 import org.springframework.beans.BeansException;
38 import org.springframework.beans.FatalBeanException;
39 import org.springframework.beans.MutablePropertyValues;
40 import org.springframework.beans.PropertyValue;
41 import org.springframework.beans.PropertyValues;
42 import org.springframework.beans.factory.BeanClassLoaderAware;
43 import org.springframework.beans.factory.BeanCreationException;
44 import org.springframework.beans.factory.BeanCurrentlyInCreationException;
45 import org.springframework.beans.factory.BeanDefinitionStoreException;
46 import org.springframework.beans.factory.BeanFactory;
47 import org.springframework.beans.factory.BeanFactoryAware;
48 import org.springframework.beans.factory.BeanNameAware;
49 import org.springframework.beans.factory.FactoryBean;
50 import org.springframework.beans.factory.InitializingBean;
51 import org.springframework.beans.factory.UnsatisfiedDependencyException;
52 import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
53 import org.springframework.beans.factory.config.BeanPostProcessor;
54 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
55 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
56 import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
57 import org.springframework.core.CollectionFactory;
58 import org.springframework.util.ReflectionUtils;
59 import org.springframework.util.StringUtils;
60
61 /**
62  * Abstract BeanFactory superclass that implements default bean creation,
63  * with the full capabilities specified by the {@link RootBeanDefinition} class.
64  * Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
65  * interface in addition to AbstractBeanFactory's {@link #createBean} method.
66  *
67  * <p>Provides bean creation (with constructor resolution), property population,
68  * wiring (including autowiring), and initialization. Handles runtime bean
69  * references, resolves managed collections, calls initialization methods, etc.
70  * Supports autowiring constructors, properties by name, and properties by type.
71  *
72  * <p>The main template method to be implemented by subclasses is
73  * {@link #findAutowireCandidates}, used for autowiring by type. In case of
74  * a factory which is capable of searching its bean definitions, matching
75  * beans will typically be implemented through such a search. For other
76  * factory styles, simplified matching algorithms can be implemented.
77  *
78  * <p>Note that this class does <i>not</i> assume or implement bean definition
79  * registry capabilities. See {@link DefaultListableBeanFactory} for an implementation
80  * of the {@link org.springframework.beans.factory.ListableBeanFactory} and
81  * {@link BeanDefinitionRegistry} interfaces, which represent the API and SPI
82  * view of such a factory, respectively.
83  *
84  * @author Rod Johnson
85  * @author Juergen Hoeller
86  * @author Rob Harrop
87  * @since 13.02.2004
88  * @see AutowireCapableBeanFactory
89  * @see AbstractBeanFactory#createBean
90  * @see RootBeanDefinition
91  * @see #findAutowireCandidates
92  * @see DefaultListableBeanFactory
93  * @see BeanDefinitionRegistry
94  */

95 public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
96         implements AutowireCapableBeanFactory {
97
98     private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
99
100     /** Whether to automatically try to resolve circular references between beans */
101     private boolean allowCircularReferences = true;
102
103     /**
104      * Whether to resort to injecting a raw bean instance in case of circular reference,
105      * even if the injected bean eventually got wrapped.
106      */

107     private boolean allowRawInjectionDespiteWrapping = false;
108
109     /**
110      * Dependency types to ignore on dependency check and autowire, as Set of
111      * Class objects: for example, String. Default is none.
112      */

113     private final Set JavaDoc ignoredDependencyTypes = new HashSet JavaDoc();
114
115     /**
116      * Dependency interfaces to ignore on dependency check and autowire, as Set of
117      * Class objects. By default, only the BeanFactory interface is ignored.
118      */

119     private final Set JavaDoc ignoredDependencyInterfaces = new HashSet JavaDoc();
120
121     /** Cache of unfinished FactoryBean instances: FactoryBean name --> BeanWrapper */
122     private final Map JavaDoc factoryBeanInstanceCache = new HashMap JavaDoc();
123
124     /** Cache of analyzed PropertyDescriptors for dependency checking: PropertyDescriptor -> Boolean */
125     private final Map JavaDoc excludedPropertyDescriptorsCache = CollectionFactory.createIdentityMapIfPossible(16);
126
127
128     /**
129      * Create a new AbstractAutowireCapableBeanFactory.
130      */

131     public AbstractAutowireCapableBeanFactory() {
132         super();
133         ignoreDependencyInterface(BeanNameAware.class);
134         ignoreDependencyInterface(BeanFactoryAware.class);
135         ignoreDependencyInterface(BeanClassLoaderAware.class);
136     }
137
138     /**
139      * Create a new AbstractAutowireCapableBeanFactory with the given parent.
140      * @param parentBeanFactory parent bean factory, or <code>null</code> if none
141      */

142     public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
143         this();
144         setParentBeanFactory(parentBeanFactory);
145     }
146
147
148     /**
149      * Set the instantiation strategy to use for creating bean instances.
150      * Default is CglibSubclassingInstantiationStrategy.
151      * @see CglibSubclassingInstantiationStrategy
152      */

153     public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
154         this.instantiationStrategy = instantiationStrategy;
155     }
156
157     /**
158      * Return the instantiation strategy to use for creating bean instances.
159      */

160     protected InstantiationStrategy getInstantiationStrategy() {
161         return instantiationStrategy;
162     }
163
164     /**
165      * Set whether to allow circular references between beans - and automatically
166      * try to resolve them.
167      * <p>Note that circular reference resolution means that one of the involved beans
168      * will receive a reference to another bean that is not fully initialized yet.
169      * This can lead to subtle and not-so-subtle side effects on initialization;
170      * it does work fine for many scenarios, though.
171      * <p>Default is "true". Turn this off to throw an exception when encountering
172      * a circular reference, disallowing them completely.
173      * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
174      * between your beans. Refactor your application logic to have the two beans
175      * involved delegate to a third bean that encapsulates their common logic.
176      */

177     public void setAllowCircularReferences(boolean allowCircularReferences) {
178         this.allowCircularReferences = allowCircularReferences;
179     }
180
181     /**
182      * Set whether to allow the raw injection of a bean instance into some other
183      * bean's property, despite the injected bean eventually getting wrapped
184      * (for example, through AOP auto-proxying).
185      * <p>This will only be used as a last resort in case of a circular reference
186      * that cannot be resolved otherwise: essentially, preferring a raw instance
187      * getting injected over a failure of the entire bean wiring process.
188      * <p>Default is "false", as of Spring 2.0. Turn this on to allow for non-wrapped
189      * raw beans injected into some of your references, which was Spring 1.2's
190      * (arguably unclean) default behavior.
191      * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
192      * between your beans, in particular with auto-proxying involved.
193      * @see #setAllowCircularReferences
194      */

195     public void setAllowRawInjectionDespiteWrapping(boolean allowRawInjectionDespiteWrapping) {
196         this.allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping;
197     }
198
199     /**
200      * Ignore the given dependency type for autowiring:
201      * for example, String. Default is none.
202      */

203     public void ignoreDependencyType(Class JavaDoc type) {
204         this.ignoredDependencyTypes.add(type);
205     }
206
207     /**
208      * Ignore the given dependency interface for autowiring.
209      * <p>This will typically be used by application contexts to register
210      * dependencies that are resolved in other ways, like BeanFactory through
211      * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
212      * <p>By default, only the BeanFactoryAware interface is ignored.
213      * For further types to ignore, invoke this method for each type.
214      * @see org.springframework.beans.factory.BeanFactoryAware
215      * @see org.springframework.context.ApplicationContextAware
216      */

217     public void ignoreDependencyInterface(Class JavaDoc ifc) {
218         this.ignoredDependencyInterfaces.add(ifc);
219     }
220
221
222     public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
223         super.copyConfigurationFrom(otherFactory);
224         if (otherFactory instanceof AbstractAutowireCapableBeanFactory) {
225             AbstractAutowireCapableBeanFactory otherAutowireFactory =
226                     (AbstractAutowireCapableBeanFactory) otherFactory;
227             this.instantiationStrategy = otherAutowireFactory.instantiationStrategy;
228             this.allowCircularReferences = otherAutowireFactory.allowCircularReferences;
229             this.ignoredDependencyTypes.addAll(otherAutowireFactory.ignoredDependencyTypes);
230             this.ignoredDependencyInterfaces.addAll(otherAutowireFactory.ignoredDependencyInterfaces);
231         }
232     }
233
234
235     //---------------------------------------------------------------------
236
// Implementation of AutowireCapableBeanFactory interface
237
//---------------------------------------------------------------------
238

239     public Object JavaDoc createBean(Class JavaDoc beanClass, int autowireMode, boolean dependencyCheck)
240             throws BeansException {
241
242         // Use non-singleton bean definition, to avoid registering bean as dependent bean.
243
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
244         bd.setSingleton(false);
245         return createBean(beanClass.getName(), bd, null);
246     }
247
248     public Object JavaDoc autowire(Class JavaDoc beanClass, int autowireMode, boolean dependencyCheck)
249             throws BeansException {
250
251         // Use non-singleton bean definition, to avoid registering bean as dependent bean.
252
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
253         bd.setSingleton(false);
254         if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
255             return autowireConstructor(beanClass.getName(), bd).getWrappedInstance();
256         }
257         else {
258             Object JavaDoc bean = getInstantiationStrategy().instantiate(bd, null, this);
259             populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
260             return bean;
261         }
262     }
263
264     public void autowireBeanProperties(Object JavaDoc existingBean, int autowireMode, boolean dependencyCheck)
265             throws BeansException {
266
267         if (autowireMode != AUTOWIRE_BY_NAME && autowireMode != AUTOWIRE_BY_TYPE) {
268             throw new IllegalArgumentException JavaDoc("Just constants AUTOWIRE_BY_NAME and AUTOWIRE_BY_TYPE allowed");
269         }
270         // Use non-singleton bean definition, to avoid registering bean as dependent bean.
271
RootBeanDefinition bd = new RootBeanDefinition(existingBean.getClass(), autowireMode, dependencyCheck);
272         bd.setSingleton(false);
273         populateBean(existingBean.getClass().getName(), bd, new BeanWrapperImpl(existingBean));
274     }
275
276     public void applyBeanPropertyValues(Object JavaDoc existingBean, String JavaDoc beanName) throws BeansException {
277         RootBeanDefinition bd = getMergedBeanDefinition(beanName, true);
278         BeanWrapper bw = new BeanWrapperImpl(existingBean);
279         initBeanWrapper(bw);
280         applyPropertyValues(beanName, bd, bw, bd.getPropertyValues());
281     }
282
283     public Object JavaDoc configureBean(Object JavaDoc existingBean, String JavaDoc beanName) throws BeansException {
284         RootBeanDefinition bd = getMergedBeanDefinition(beanName, true);
285         BeanWrapper bw = new BeanWrapperImpl(existingBean);
286         initBeanWrapper(bw);
287         populateBean(beanName, bd, bw);
288         return initializeBean(beanName, existingBean, bd);
289     }
290
291     public Object JavaDoc initializeBean(Object JavaDoc existingBean, String JavaDoc beanName) {
292         return initializeBean(beanName, existingBean, null);
293     }
294
295     public Object JavaDoc applyBeanPostProcessorsBeforeInitialization(Object JavaDoc existingBean, String JavaDoc beanName)
296             throws BeansException {
297
298         if (logger.isTraceEnabled()) {
299             logger.trace("Invoking BeanPostProcessors before initialization of bean '" + beanName + "'");
300         }
301         Object JavaDoc result = existingBean;
302         for (Iterator JavaDoc it = getBeanPostProcessors().iterator(); it.hasNext();) {
303             BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
304             result = beanProcessor.postProcessBeforeInitialization(result, beanName);
305         }
306         return result;
307     }
308
309     public Object JavaDoc applyBeanPostProcessorsAfterInitialization(Object JavaDoc existingBean, String JavaDoc beanName)
310             throws BeansException {
311
312         if (logger.isTraceEnabled()) {
313             logger.trace("Invoking BeanPostProcessors after initialization of bean '" + beanName + "'");
314         }
315         Object JavaDoc result = existingBean;
316         for (Iterator JavaDoc it = getBeanPostProcessors().iterator(); it.hasNext();) {
317             BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
318             result = beanProcessor.postProcessAfterInitialization(result, beanName);
319         }
320         return result;
321     }
322
323
324     //---------------------------------------------------------------------
325
// Implementation of relevant AbstractBeanFactory template methods
326
//---------------------------------------------------------------------
327

328     /**
329      * Central method of this class: creates a bean instance,
330      * populates the bean instance, applies post-processors, etc.
331      * <p>Differentiates between default bean instantiation, use of a
332      * factory method, and autowiring a constructor.
333      * @see #instantiateBean
334      * @see #instantiateUsingFactoryMethod
335      * @see #autowireConstructor
336      */

337     protected Object JavaDoc createBean(String JavaDoc beanName, RootBeanDefinition mbd, Object JavaDoc[] args)
338             throws BeanCreationException {
339
340         // Guarantee initialization of beans that the current one depends on.
341
if (mbd.getDependsOn() != null) {
342             for (int i = 0; i < mbd.getDependsOn().length; i++) {
343                 getBean(mbd.getDependsOn()[i]);
344             }
345         }
346
347         if (logger.isDebugEnabled()) {
348             logger.debug("Creating instance of bean '" + beanName + "' with merged definition [" + mbd + "]");
349         }
350
351         // Make sure bean class is actually resolved at this point.
352
Class JavaDoc beanClass = resolveBeanClass(mbd, beanName);
353
354         // Prepare method overrides.
355
try {
356             mbd.prepareMethodOverrides();
357         }
358         catch (BeanDefinitionValidationException ex) {
359             throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
360                     beanName, "Validation of method overrides failed", ex);
361         }
362
363         String JavaDoc errorMessage = null;
364
365         try {
366             // Instantiate the bean.
367
errorMessage = "BeanPostProcessor before instantiation of bean failed";
368
369             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
370
if (beanClass != null &&
371                     !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
372                 Object JavaDoc bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
373                 if (bean != null) {
374                     bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
375                     return bean;
376                 }
377             }
378
379             // Instantiate the bean.
380
errorMessage = "Instantiation of bean failed";
381
382             BeanWrapper instanceWrapper = null;
383             if (mbd.isSingleton()) {
384                 synchronized (getSingletonMutex()) {
385                     instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
386                 }
387             }
388
389             if (instanceWrapper == null) {
390                 instanceWrapper = createBeanInstance(beanName, mbd, args);
391             }
392             Object JavaDoc bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
393
394             // Eagerly cache singletons to be able to resolve circular references
395
// even when triggered by lifecycle interfaces like BeanFactoryAware.
396
if (mbd.isSingleton() && this.allowCircularReferences &&
397                     isSingletonCurrentlyInCreation(beanName)) {
398                 if (logger.isDebugEnabled()) {
399                     logger.debug("Eagerly caching bean '" + beanName +
400                             "' to allow for resolving potential circular references");
401                 }
402                 addSingleton(beanName, bean);
403             }
404
405             // Initialize the bean instance.
406
errorMessage = "Initialization of bean failed";
407
408             // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
409
// state of the bean before properties are set. This can be used, for example,
410
// to support styles of field injection.
411
boolean continueWithPropertyPopulation = true;
412
413             if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
414                 for (Iterator JavaDoc it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
415                     BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
416                     if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
417                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
418                         if (!ibp.postProcessAfterInstantiation(bean, beanName)) {
419                             continueWithPropertyPopulation = false;
420                             break;
421                         }
422                     }
423                 }
424             }
425
426             if (continueWithPropertyPopulation) {
427                 populateBean(beanName, mbd, instanceWrapper);
428             }
429
430             Object JavaDoc originalBean = bean;
431             bean = initializeBean(beanName, bean, mbd);
432
433             if (!this.allowRawInjectionDespiteWrapping && originalBean != bean &&
434                     mbd.isSingleton() && hasDependentBean(beanName)) {
435                 throw new BeanCurrentlyInCreationException(beanName,
436                         "Bean with name '" + beanName + "' has been injected into other beans " +
437                         getDependentBeans(beanName) + " in its raw version as part of a circular reference, " +
438                         "but has eventually been wrapped (for example as part of auto-proxy creation). " +
439                         "This means that said other beans do not use the final version of the bean. " +
440                         "This is often the result of over-eager type matching - consider using " +
441                         "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
442             }
443
444             // Register bean as disposable, and also as dependent on specified "dependsOn" beans.
445
registerDisposableBeanIfNecessary(beanName, originalBean, mbd);
446
447             return bean;
448         }
449
450         catch (BeanCreationException ex) {
451             throw ex;
452         }
453         catch (Throwable JavaDoc ex) {
454             throw new BeanCreationException(
455                     mbd.getResourceDescription(), beanName, errorMessage, ex);
456         }
457     }
458
459     /**
460      * Predict the eventual bean type for the given bean.
461      * @param beanName the name of the bean
462      * @param mbd the merged bean definition to determine the type for
463      * @return the type of the bean, or <code>null</code> if not predictable
464      */

465     protected Class JavaDoc predictBeanType(String JavaDoc beanName, RootBeanDefinition mbd) {
466         Class JavaDoc beanClass = null;
467         if (mbd.getFactoryMethodName() != null) {
468             beanClass = getTypeForFactoryMethod(beanName, mbd);
469         }
470         else {
471             beanClass = resolveBeanClass(mbd, beanName);
472         }
473         // Apply SmartInstantiationAwareBeanPostProcessors to predict the
474
// eventual type after a before-instantiation shortcut.
475
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
476             for (Iterator JavaDoc it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
477                 BeanPostProcessor bp = (BeanPostProcessor) it.next();
478                 if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
479                     SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
480                     Class JavaDoc processedType = ibp.predictBeanType(beanClass, beanName);
481                     if (processedType != null) {
482                         return processedType;
483                     }
484                 }
485             }
486         }
487         return beanClass;
488     }
489
490     /**
491      * Determine the bean type for the given bean definition which is based on
492      * a factory method. Only called if there is no singleton instance registered
493      * for the target bean already.
494      * <p>This implementation determines the type matching {@link #createBean}'s
495      * different creation strategies. As far as possible, we'll perform static
496      * type checking to avoid creation of the target bean.
497      * @param beanName the name of the bean (for error handling purposes)
498      * @param mbd the merged bean definition for the bean
499      * @return the type for the bean if determinable, or <code>null</code> else
500      * @see #createBean
501      */

502     protected Class JavaDoc getTypeForFactoryMethod(String JavaDoc beanName, RootBeanDefinition mbd) {
503         Class JavaDoc factoryClass = null;
504         boolean isStatic = true;
505
506         if (mbd.getFactoryBeanName() != null) {
507             // Check declared factory method return type on factory class.
508
factoryClass = getType(mbd.getFactoryBeanName());
509             isStatic = false;
510         }
511         else {
512             // Check declared factory method return type on bean class.
513
factoryClass = resolveBeanClass(mbd, beanName);
514         }
515
516         if (factoryClass == null) {
517             return null;
518         }
519
520         // If all factory methods have the same return type, return that type.
521
// Can't clearly figure out exact method due to type converting / autowiring!
522
int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
523         Method JavaDoc[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
524         Set JavaDoc returnTypes = new HashSet JavaDoc(1);
525         for (int i = 0; i < candidates.length; i++) {
526             Method JavaDoc factoryMethod = candidates[i];
527             if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic &&
528                     factoryMethod.getName().equals(mbd.getFactoryMethodName()) &&
529                     factoryMethod.getParameterTypes().length >= minNrOfArgs) {
530                 returnTypes.add(factoryMethod.getReturnType());
531             }
532         }
533
534         if (returnTypes.size() == 1) {
535             // Clear return type found: all factory methods return same type.
536
return (Class JavaDoc) returnTypes.iterator().next();
537         }
538         else {
539             // Ambiguous return types found: return null to indicate "not determinable".
540
return null;
541         }
542     }
543
544     /**
545      * This implementation checks the FactoryBean's <code>getObjectType</code> method
546      * on a plain instance of the FactoryBean, without bean properties applied yet.
547      * If this doesn't return a type yet, a full creation of the FactoryBean is
548      * used as fallback (through delegation to the superclass's implementation).
549      * <p>The shortcut check for a FactoryBean is only applied in case of a singleton
550      * FactoryBean. If the FactoryBean instance itself is not kept as singleton,
551      * it will be fully created to check the type of its exposed object.
552      */

553     protected Class JavaDoc getTypeForFactoryBean(String JavaDoc beanName, RootBeanDefinition mbd) {
554         FactoryBean fb = (mbd.isSingleton() ?
555                 getSingletonFactoryBeanForTypeCheck(beanName, mbd) :
556                 getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
557
558         if (fb != null) {
559             // Try to obtain the FactoryBean's object type from this early stage of the instance.
560
try {
561                 Class JavaDoc type = fb.getObjectType();
562                 if (type != null) {
563                     return type;
564                 }
565             }
566             catch (Throwable JavaDoc ex) {
567                 // Thrown from the FactoryBean's getObjectType implementation.
568
logger.warn("FactoryBean threw exception from getObjectType, despite the contract saying " +
569                         "that it should return null if the type of its object cannot be determined yet", ex);
570             }
571         }
572
573         // No type found - fall back to full creation of the FactoryBean instance.
574
return super.getTypeForFactoryBean(beanName, mbd);
575     }
576
577
578     //---------------------------------------------------------------------
579
// Implementation methods
580
//---------------------------------------------------------------------
581

582     /**
583      * Obtain a "shortcut" singleton FactoryBean instance to use for a
584      * <code>getObjectType()</code> call, without full initialization
585      * of the FactoryBean.
586      * @param beanName name of the bean
587      * @param mbd the bean definition for the bean
588      * @return the FactoryBean instance, or <code>null</code> to indicate
589      * that we couldn't obtain a shortcut FactoryBean instance
590      */

591     private FactoryBean getSingletonFactoryBeanForTypeCheck(String JavaDoc beanName, RootBeanDefinition mbd) {
592         synchronized (getSingletonMutex()) {
593             BeanWrapper bw = (BeanWrapper) this.factoryBeanInstanceCache.get(beanName);
594             if (bw != null) {
595                 return (FactoryBean) bw.getWrappedInstance();
596             }
597             if (isSingletonCurrentlyInCreation(beanName)) {
598                 return null;
599             }
600             Object JavaDoc instance = null;
601             try {
602                 // Mark this bean as currently in creation, even if just partially.
603
beforeSingletonCreation(beanName);
604                 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
605
Class JavaDoc beanClass = resolveBeanClass(mbd, beanName);
606                 if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
607                     Object JavaDoc bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
608                     if (bean != null) {
609                         instance = applyBeanPostProcessorsAfterInitialization(bean, beanName);
610                     }
611                 }
612                 if (instance == null) {
613                     bw = createBeanInstance(beanName, mbd, null);
614                     instance = bw.getWrappedInstance();
615                 }
616             }
617             finally {
618                 // Finished partial creation of this bean.
619
afterSingletonCreation(beanName);
620             }
621             if (!(instance instanceof FactoryBean)) {
622                 throw new BeanCreationException(beanName,
623                         "Bean instance of type [" + instance.getClass() + "] is not a FactoryBean");
624             }
625             if (bw != null) {
626                 this.factoryBeanInstanceCache.put(beanName, bw);
627             }
628             return (FactoryBean) instance;
629         }
630     }
631
632     /**
633      * Obtain a "shortcut" non-singleton FactoryBean instance to use for a
634      * <code>getObjectType()</code> call, without full initialization
635      * of the FactoryBean.
636      * @param beanName name of the bean
637      * @param mbd the bean definition for the bean
638      * @return the FactoryBean instance, or <code>null</code> to indicate
639      * that we couldn't obtain a shortcut FactoryBean instance
640      */

641     private FactoryBean getNonSingletonFactoryBeanForTypeCheck(String JavaDoc beanName, RootBeanDefinition mbd) {
642         if (isPrototypeCurrentlyInCreation(beanName)) {
643             return null;
644         }
645         Object JavaDoc instance = null;
646         try {
647             // Mark this bean as currently in creation, even if just partially.
648
beforePrototypeCreation(beanName);
649             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
650
Class JavaDoc beanClass = resolveBeanClass(mbd, beanName);
651             if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
652                 Object JavaDoc bean = applyBeanPostProcessorsBeforeInstantiation(beanClass, beanName);
653                 if (bean != null) {
654                     instance = applyBeanPostProcessorsAfterInitialization(bean, beanName);
655                 }
656             }
657             if (instance == null) {
658                 BeanWrapper bw = createBeanInstance(beanName, mbd, null);
659                 instance = bw.getWrappedInstance();
660             }
661         }
662         finally {
663             // Finished partial creation of this bean.
664
afterPrototypeCreation(beanName);
665         }
666         if (!(instance instanceof FactoryBean)) {
667             throw new BeanCreationException(beanName,
668                     "Bean instance of type [" + instance.getClass() + "] is not a FactoryBean");
669         }
670         return (FactoryBean) instance;
671     }
672
673     /**
674      * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
675      * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods.
676      * <p>Any returned object will be used as the bean instead of actually instantiating
677      * the target bean. A <code>null</code> return value from the post-processor will
678      * result in the target bean being instantiated.
679      * @param beanClass the class of the bean to be instantiated
680      * @param beanName the name of the bean
681      * @return the bean object to use instead of a default instance of the target bean, or <code>null</code>
682      * @throws BeansException if any post-processing failed
683      * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
684      */

685     protected Object JavaDoc applyBeanPostProcessorsBeforeInstantiation(Class JavaDoc beanClass, String JavaDoc beanName)
686             throws BeansException {
687
688         if (logger.isTraceEnabled()) {
689             logger.trace("Invoking BeanPostProcessors before instantiation of bean '" + beanName + "'");
690         }
691         for (Iterator JavaDoc it = getBeanPostProcessors().iterator(); it.hasNext();) {
692             BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
693             if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
694                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
695                 Object JavaDoc result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
696                 if (result != null) {
697                     return result;
698                 }
699             }
700         }
701         return null;
702     }
703
704     /**
705      * Create a new instance for the specified bean, using an appropriate instantiation strategy:
706      * factory method, constructor autowiring, or simple instantiation.
707      * @param beanName name of the bean
708      * @param mbd the bean definition for the bean
709      * @param args arguments to use if creating a prototype using explicit arguments to a
710      * static factory method. It is invalid to use a non-null args value in any other case.
711      * @return BeanWrapper for the new instance
712      * @see #instantiateUsingFactoryMethod
713      * @see #autowireConstructor
714      * @see #instantiateBean
715      */

716     protected BeanWrapper createBeanInstance(String JavaDoc beanName, RootBeanDefinition mbd, Object JavaDoc[] args) {
717         BeanWrapper instanceWrapper = null;
718         if (mbd.getFactoryMethodName() != null) {
719             instanceWrapper = instantiateUsingFactoryMethod(beanName, mbd, args);
720         }
721         else if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
722                 mbd.hasConstructorArgumentValues() ) {
723             instanceWrapper = autowireConstructor(beanName, mbd);
724         }
725         else {
726             // No special handling: simply use no-arg constructor.
727
instanceWrapper = instantiateBean(beanName, mbd);
728         }
729         return instanceWrapper;
730     }
731
732     /**
733      * Instantiate the given bean using its default constructor.
734      * @param beanName name of the bean
735      * @param mbd the bean definition for the bean
736      * @return BeanWrapper for the new instance
737      */

738     protected BeanWrapper instantiateBean(String JavaDoc beanName, RootBeanDefinition mbd) {
739         Object JavaDoc beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
740         BeanWrapper bw = new BeanWrapperImpl(beanInstance);
741         initBeanWrapper(bw);
742         return bw;
743     }
744
745     /**
746      * Instantiate the bean using a named factory method. The method may be static, if the
747      * mbd parameter specifies a class, rather than a factoryBean, or
748      * an instance variable on a factory object itself configured using Dependency Injection.
749      * <p>Implementation requires iterating over the static or instance methods with the
750      * name specified in the RootBeanDefinition (the method may be overloaded) and trying
751      * to match with the parameters. We don't have the types attached to constructor args,
752      * so trial and error is the only way to go here. The explicitArgs array may contain
753      * argument values passed in programmatically via the corresponding getBean method.
754      * @param beanName name of the bean
755      * @param mbd the bean definition for the bean
756      * @param explicitArgs argument values passed in programmatically via the getBean
757      * method, or <code>null</code> if none (-> use constructor argument values from bean definition)
758      * @return BeanWrapper for the new instance
759      * @see #getBean(String, Object[])
760      */

761     protected BeanWrapper instantiateUsingFactoryMethod(
762             String JavaDoc beanName, RootBeanDefinition mbd, Object JavaDoc[] explicitArgs) {
763
764         ConstructorResolver constructorResolver = new ConstructorResolverAdapter();
765         return constructorResolver.instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
766     }
767
768     /**
769      * "autowire constructor" (with constructor arguments by type) behavior.
770      * Also applied if explicit constructor argument values are specified,
771      * matching all remaining arguments with beans from the bean factory.
772      * <p>This corresponds to constructor injection: In this mode, a Spring
773      * bean factory is able to host components that expect constructor-based
774      * dependency resolution.
775      * @param beanName name of the bean
776      * @param mbd the bean definition for the bean
777      * @return BeanWrapper for the new instance
778      */

779     protected BeanWrapper autowireConstructor(String JavaDoc beanName, RootBeanDefinition mbd) {
780         ConstructorResolver constructorResolver = new ConstructorResolverAdapter();
781         return constructorResolver.autowireConstructor(beanName, mbd);
782     }
783
784     /**
785      * Populate the bean instance in the given BeanWrapper with the property values
786      * from the bean definition.
787      * @param beanName name of the bean
788      * @param mbd the bean definition for the bean
789      * @param bw BeanWrapper with bean instance
790      */

791     protected void populateBean(String JavaDoc beanName, RootBeanDefinition mbd, BeanWrapper bw) {
792         PropertyValues pvs = mbd.getPropertyValues();
793
794         if (bw == null) {
795             if (!pvs.isEmpty()) {
796                 throw new BeanCreationException(beanName, "Cannot apply property values to null instance");
797             }
798             else {
799                 // Skip property population phase for null instance.
800
return;
801             }
802         }
803
804         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
805                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
806             MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
807
808             // Add property values based on autowire by name if applicable.
809
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
810                 autowireByName(beanName, mbd, bw, newPvs);
811             }
812
813             // Add property values based on autowire by type if applicable.
814
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
815                 autowireByType(beanName, mbd, bw, newPvs);
816             }
817
818             pvs = newPvs;
819         }
820
821         boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
822         boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
823
824         if (hasInstAwareBpps || needsDepCheck) {
825             PropertyDescriptor JavaDoc[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
826             if (hasInstAwareBpps) {
827                 for (Iterator JavaDoc it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
828                     BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
829                     if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
830                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
831                         pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
832                         if (pvs == null) {
833                             return;
834                         }
835                     }
836                 }
837             }
838             if (needsDepCheck) {
839                 checkDependencies(beanName, mbd, filteredPds, pvs);
840             }
841         }
842
843         applyPropertyValues(beanName, mbd, bw, pvs);
844     }
845
846     /**
847      * Fill in any missing property values with references to
848      * other beans in this factory if autowire is set to "byName".
849      * @param beanName name of the bean we're wiring up.
850      * Useful for debugging messages; not used functionally.
851      * @param mbd bean definition to update through autowiring
852      * @param bw BeanWrapper from which we can obtain information about the bean
853      * @param pvs the PropertyValues to register wired objects with
854      */

855     protected void autowireByName(
856             String JavaDoc beanName, RootBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
857
858         String JavaDoc[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
859         for (int i = 0; i < propertyNames.length; i++) {
860             String JavaDoc propertyName = propertyNames[i];
861             if (containsBean(propertyName)) {
862                 Object JavaDoc bean = getBean(propertyName);
863                 pvs.addPropertyValue(propertyName, bean);
864                 if (mbd.isSingleton()) {
865                     registerDependentBean(propertyName, beanName);
866                 }
867                 if (logger.isDebugEnabled()) {
868                     logger.debug("Added autowiring by name from bean name '" + beanName +
869                         "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
870                 }
871             }
872             else {
873                 if (logger.isTraceEnabled()) {
874                     logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
875                             "' by name: no matching bean found");
876                 }
877             }
878         }
879     }
880
881     /**
882      * Abstract method defining "autowire by type" (bean properties by type) behavior.
883      * <p>This is like PicoContainer default, in which there must be exactly one bean
884      * of the property type in the bean factory. This makes bean factories simple to
885      * configure for small namespaces, but doesn't work as well as standard Spring
886      * behavior for bigger applications.
887      * @param beanName the name of the bean to autowire by type
888      * @param mbd the merged bean definition to update through autowiring
889      * @param bw BeanWrapper from which we can obtain information about the bean
890      * @param pvs the PropertyValues to register wired objects with
891      */

892     protected void autowireByType(
893             String JavaDoc beanName, RootBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
894
895         String JavaDoc[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
896         for (int i = 0; i < propertyNames.length; i++) {
897             String JavaDoc propertyName = propertyNames[i];
898             // look for a matching type
899
Class JavaDoc requiredType = bw.getPropertyDescriptor(propertyName).getPropertyType();
900             Map JavaDoc matchingBeans = findAutowireCandidates(beanName, requiredType);
901             // Let's see how many matching beans we got...
902
int count = matchingBeans.size();
903             if (count == 1) {
904                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) matchingBeans.entrySet().iterator().next();
905                 String JavaDoc autowiredBeanName = (String JavaDoc) entry.getKey();
906                 Object JavaDoc autowiredBean = entry.getValue();
907                 pvs.addPropertyValue(propertyName, autowiredBean);
908                 if (mbd.isSingleton()) {
909                     registerDependentBean(autowiredBeanName, beanName);
910                 }
911                 if (logger.isDebugEnabled()) {
912                     logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
913                             propertyName + "' to bean named '" + autowiredBeanName + "'");
914                 }
915             }
916             else if (count > 1) {
917                 throw new UnsatisfiedDependencyException(
918                         mbd.getResourceDescription(), beanName, propertyName,
919                         "There are " + matchingBeans.size() + " beans of type [" + requiredType.getName() +
920                         "] available for autowiring by type: " + matchingBeans.keySet() +
921                         ". There should have been exactly 1 to be able to autowire property '" +
922                         propertyName + "' of bean '" + beanName + "'. Consider using autowiring by name instead.");
923             }
924             else {
925                 if (logger.isTraceEnabled()) {
926                     logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
927                             "' by type: no matching bean found");
928                 }
929             }
930         }
931     }
932
933     /**
934      * Return an array of non-simple bean properties that are unsatisfied.
935      * These are probably unsatisfied references to other beans in the
936      * factory. Does not include simple properties like primitives or Strings.
937      * @param mbd the merged bean definition the bean was created with
938      * @param bw the BeanWrapper the bean was created with
939      * @return an array of bean property names
940      * @see org.springframework.beans.BeanUtils#isSimpleProperty
941      */

942     protected String JavaDoc[] unsatisfiedNonSimpleProperties(RootBeanDefinition mbd, BeanWrapper bw) {
943         Set JavaDoc result = new TreeSet JavaDoc();
944         PropertyValues pvs = mbd.getPropertyValues();
945         PropertyDescriptor JavaDoc[] pds = bw.getPropertyDescriptors();
946         for (int i = 0; i < pds.length; i++) {
947             if (pds[i].getWriteMethod() != null && !isExcludedFromDependencyCheck(pds[i]) &&
948                     !pvs.contains(pds[i].getName()) && !BeanUtils.isSimpleProperty(pds[i].getPropertyType())) {
949                 result.add(pds[i].getName());
950             }
951         }
952         return StringUtils.toStringArray(result);
953     }
954
955     /**
956      * Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
957      * excluding ignored dependency types or properties defined on ignored
958      * dependency interfaces.
959      * @param bw the BeanWrapper the bean was created with
960      * @return the filtered PropertyDescriptors
961      * @see #isExcludedFromDependencyCheck
962      */

963     protected PropertyDescriptor JavaDoc[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
964         List JavaDoc pds = new LinkedList JavaDoc(Arrays.asList(bw.getPropertyDescriptors()));
965         for (Iterator JavaDoc it = pds.iterator(); it.hasNext();) {
966             PropertyDescriptor JavaDoc pd = (PropertyDescriptor JavaDoc) it.next();
967             if (isExcludedFromDependencyCheck(pd)) {
968                 it.remove();
969             }
970         }
971         return (PropertyDescriptor JavaDoc[]) pds.toArray(new PropertyDescriptor JavaDoc[pds.size()]);
972     }
973
974     /**
975      * Determine whether the given bean property is excluded from dependency checks.
976      * <p>This implementation excludes properties defined by CGLIB and
977      * properties whose type matches an ignored dependency type or which
978      * are defined by an ignored dependency interface.
979      * @param pd the PropertyDescriptor of the bean property
980      * @return whether the bean property is excluded
981      * @see #ignoreDependencyType(Class)
982      * @see #ignoreDependencyInterface(Class)
983      */

984     protected boolean isExcludedFromDependencyCheck(PropertyDescriptor JavaDoc pd) {
985         synchronized (this.excludedPropertyDescriptorsCache) {
986             Boolean JavaDoc marker = (Boolean JavaDoc) this.excludedPropertyDescriptorsCache.get(pd);
987             if (marker == null) {
988                 marker = new Boolean JavaDoc(AutowireUtils.isExcludedFromDependencyCheck(pd) ||
989                     this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
990                     AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
991                 this.excludedPropertyDescriptorsCache.put(pd, marker);
992             }
993             return marker.booleanValue();
994         }
995     }
996
997     /**
998      * Perform a dependency check that all properties exposed have been set,
999      * if desired. Dependency checks can be objects (collaborating beans),
1000     * simple (primitives and String), or all (both).
1001     * @param beanName the name of the bean
1002     * @param mbd the merged bean definition the bean was created with
1003     * @param pds the relevant property descriptors for the target bean
1004     * @param pvs the property values to be applied to the bean
1005     * @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor)
1006     */

1007    protected void checkDependencies(
1008            String JavaDoc beanName, RootBeanDefinition mbd, PropertyDescriptor JavaDoc[] pds, PropertyValues pvs)
1009            throws UnsatisfiedDependencyException {
1010
1011        int dependencyCheck = mbd.getDependencyCheck();
1012        for (int i = 0; i < pds.length; i++) {
1013            if (pds[i].getWriteMethod() != null && !pvs.contains(pds[i].getName())) {
1014                boolean isSimple = BeanUtils.isSimpleProperty(pds[i].getPropertyType());
1015                boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
1016                    (isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
1017                    (!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
1018                if (unsatisfied) {
1019                    throw new UnsatisfiedDependencyException(
1020                            mbd.getResourceDescription(), beanName, pds[i].getName(),
1021                            "Set this property value or disable dependency checking for this bean.");
1022                }
1023            }
1024        }
1025    }
1026
1027    /**
1028     * Apply the given property values, resolving any runtime references
1029     * to other beans in this bean factory. Must use deep copy, so we
1030     * don't permanently modify this property.
1031     * @param beanName bean name passed for better exception information
1032     * @param bw BeanWrapper wrapping the target object
1033     * @param pvs new property values
1034     */

1035    protected void applyPropertyValues(
1036            String JavaDoc beanName, RootBeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
1037
1038        if (pvs != null && !pvs.isEmpty()) {
1039            BeanDefinitionValueResolver valueResolver =
1040                    new BeanDefinitionValueResolver(this, beanName, mbd, bw);
1041
1042            // Create a deep copy, resolving any references for values.
1043
MutablePropertyValues deepCopy = new MutablePropertyValues();
1044            PropertyValue[] pvArray = pvs.getPropertyValues();
1045            for (int i = 0; i < pvArray.length; i++) {
1046                PropertyValue pv = pvArray[i];
1047                Object JavaDoc resolvedValue =
1048                        valueResolver.resolveValueIfNecessary("bean property '" + pv.getName() + "'", pv.getValue());
1049                deepCopy.addPropertyValue(pv.getName(), resolvedValue);
1050            }
1051
1052            // Set our (possibly massaged) deep copy.
1053
try {
1054                applyPropertyValues(bw, deepCopy);
1055            }
1056            catch (BeansException ex) {
1057                // Improve the message by showing the context.
1058
throw new BeanCreationException(
1059                        mbd.getResourceDescription(), beanName, "Error setting property values", ex);
1060            }
1061        }
1062    }
1063
1064
1065    /**
1066     * Initialize the given bean instance, applying factory callbacks
1067     * as well as init methods and bean post processors.
1068     * <p>Called from {@link #createBean} for traditionally defined beans,
1069     * and from {@link #initializeBean} for existing bean instances.
1070     * @param beanName the bean name in the factory (for debugging purposes)
1071     * @param bean the new bean instance we may need to initialize
1072     * @param mbd the bean definition that the bean was created with
1073     * (can also be <code>null</code>, if given an existing bean instance)
1074     * @return the initialized bean instance (potentially wrapped)
1075     * @see BeanNameAware
1076     * @see BeanClassLoaderAware
1077     * @see BeanFactoryAware
1078     * @see #applyBeanPostProcessorsBeforeInitialization
1079     * @see #invokeInitMethods
1080     * @see #applyBeanPostProcessorsAfterInitialization
1081     */

1082    protected Object JavaDoc initializeBean(String JavaDoc beanName, Object JavaDoc bean, RootBeanDefinition mbd) {
1083        if (bean instanceof BeanNameAware) {
1084            if (logger.isTraceEnabled()) {
1085                logger.trace("Invoking setBeanName on BeanNameAware bean '" + beanName + "'");
1086            }
1087            ((BeanNameAware) bean).setBeanName(beanName);
1088        }
1089
1090        if (bean instanceof BeanClassLoaderAware) {
1091            if (logger.isTraceEnabled()) {
1092                logger.trace("Invoking setBeanClassLoader on BeanClassLoaderAware bean '" + beanName + "'");
1093            }
1094            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
1095        }
1096
1097        if (bean instanceof BeanFactoryAware) {
1098            if (logger.isTraceEnabled()) {
1099                logger.trace("Invoking setBeanFactory on BeanFactoryAware bean '" + beanName + "'");
1100            }
1101            ((BeanFactoryAware) bean).setBeanFactory(this);
1102        }
1103
1104        Object JavaDoc wrappedBean = bean;
1105        if (mbd == null || !mbd.isSynthetic()) {
1106            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
1107        }
1108
1109        try {
1110            invokeInitMethods(beanName, wrappedBean, mbd);
1111        }
1112        catch (Throwable JavaDoc ex) {
1113            throw new BeanCreationException(
1114                    (mbd != null ? mbd.getResourceDescription() : null),
1115                    beanName, "Invocation of init method failed", ex);
1116        }
1117
1118        if (mbd == null || !mbd.isSynthetic()) {
1119            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
1120        }
1121        return wrappedBean;
1122    }
1123
1124    /**
1125     * Give a bean a chance to react now all its properties are set,
1126     * and a chance to know about its owning bean factory (this object).
1127     * This means checking whether the bean implements InitializingBean or defines
1128     * a custom init method, and invoking the necessary callback(s) if it does.
1129     * @param beanName the bean name in the factory (for debugging purposes)
1130     * @param bean the new bean instance we may need to initialize
1131     * @param mbd the merged bean definition that the bean was created with
1132     * (can also be <code>null</code>, if given an existing bean instance)
1133     * @throws Throwable if thrown by init methods or by the invocation process
1134     * @see #invokeCustomInitMethod
1135     */

1136    protected void invokeInitMethods(String JavaDoc beanName, Object JavaDoc bean, RootBeanDefinition mbd)
1137            throws Throwable JavaDoc {
1138
1139        if (bean instanceof InitializingBean) {
1140            if (logger.isDebugEnabled()) {
1141                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
1142            }
1143            ((InitializingBean) bean).afterPropertiesSet();
1144        }
1145
1146        if (mbd != null && mbd.getInitMethodName() != null) {
1147            invokeCustomInitMethod(
1148                    beanName, bean, mbd.getInitMethodName(), mbd.isEnforceInitMethod());
1149        }
1150    }
1151
1152    /**
1153     * Invoke the specified custom init method on the given bean.
1154     * Called by invokeInitMethods.
1155     * <p>Can be overridden in subclasses for custom resolution of init
1156     * methods with arguments.
1157     * @param beanName the bean name in the factory (for debugging purposes)
1158     * @param bean the new bean instance we may need to initialize
1159     * @param initMethodName the name of the custom init method
1160     * @param enforceInitMethod indicates whether the defined init method needs to exist
1161     * @see #invokeInitMethods
1162     */

1163    protected void invokeCustomInitMethod(
1164            String JavaDoc beanName, Object JavaDoc bean, String JavaDoc initMethodName, boolean enforceInitMethod) throws Throwable JavaDoc {
1165
1166        if (logger.isDebugEnabled()) {
1167            logger.debug("Invoking custom init method '" + initMethodName +
1168                    "' on bean with name '" + beanName + "'");
1169        }
1170        Method JavaDoc initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);
1171        if (initMethod == null) {
1172            if (enforceInitMethod) {
1173                throw new NoSuchMethodException JavaDoc("Couldn't find an init method named '" + initMethodName +
1174                        "' on bean with name '" + beanName + "'");
1175            }
1176            else {
1177                // Ignore non-existent default lifecycle methods.
1178
return;
1179            }
1180        }
1181        if (!Modifier.isPublic(initMethod.getModifiers()) ||
1182                !Modifier.isPublic(initMethod.getDeclaringClass().getModifiers())) {
1183            initMethod.setAccessible(true);
1184        }
1185        try {
1186            initMethod.invoke(bean, (Object JavaDoc[]) null);
1187        }
1188        catch (InvocationTargetException JavaDoc ex) {
1189            throw ex.getTargetException();
1190        }
1191    }
1192
1193
1194    /**
1195     * Applies the <code>postProcessAfterInitialization</code> callback of all
1196     * registered BeanPostProcessors, giving them a chance to post-process the
1197     * object obtained from FactoryBeans (for example, to auto-proxy them).
1198     * @see #applyBeanPostProcessorsAfterInitialization
1199     */

1200    protected Object JavaDoc postProcessObjectFromFactoryBean(Object JavaDoc object, String JavaDoc beanName) {
1201        return applyBeanPostProcessorsAfterInitialization(object, beanName);
1202    }
1203
1204    /**
1205     * Overridden to clear FactoryBean instance cache as well.
1206     */

1207    protected void removeSingleton(String JavaDoc beanName) {
1208        super.removeSingleton(beanName);
1209        this.factoryBeanInstanceCache.remove(beanName);
1210    }
1211
1212
1213    //---------------------------------------------------------------------
1214
// Template methods to be implemented by subclasses
1215
//---------------------------------------------------------------------
1216

1217    /**
1218     * Find bean instances that match the required type.
1219     * Called during autowiring for the specified bean.
1220     * <p>If a subclass cannot obtain information about bean names by type,
1221     * a corresponding exception should be thrown.
1222     * @param beanName the name of the bean that is about to be wired
1223     * @param requiredType the type of the autowired property or argument
1224     * @return a Map of candidate names and candidate instances that match
1225     * the required type (never <code>null</code>)
1226     * @throws BeansException in case of errors
1227     * @see #autowireByType
1228     * @see #autowireConstructor
1229     */

1230    protected Map JavaDoc findAutowireCandidates(String JavaDoc beanName, Class JavaDoc requiredType) throws BeansException {
1231        Map JavaDoc result = findMatchingBeans(requiredType);
1232        return (result != null ? result : Collections.EMPTY_MAP);
1233    }
1234
1235    /**
1236     * Find bean instances that match the required type. Called by autowiring.
1237     * @param requiredType the type of the beans to look up
1238     * @return a Map of bean names and bean instances that match the required type,
1239     * or <code>null</code> if none found
1240     * @throws BeansException in case of errors
1241     * @deprecated as of Spring 2.0.1: Override <code>findAutowireCandidates</code> instead
1242     */

1243    protected Map JavaDoc findMatchingBeans(Class JavaDoc requiredType) throws BeansException {
1244        throw new FatalBeanException("Bean lookup by type not supported by this factory");
1245    }
1246
1247
1248    //---------------------------------------------------------------------
1249
// Inner classes that serve as internal helpers
1250
//---------------------------------------------------------------------
1251

1252    /**
1253     * Subclass of ConstructorResolver that delegates to surrounding
1254     * AbstractAutowireCapableBeanFactory facilities.
1255     */

1256    private class ConstructorResolverAdapter extends ConstructorResolver {
1257
1258        public ConstructorResolverAdapter() {
1259            super(AbstractAutowireCapableBeanFactory.this, getInstantiationStrategy());
1260        }
1261
1262        protected Map JavaDoc findAutowireCandidates(String JavaDoc beanName, Class JavaDoc requiredType) throws BeansException {
1263            return AbstractAutowireCapableBeanFactory.this.findAutowireCandidates(beanName, requiredType);
1264        }
1265    }
1266
1267}
1268
Popular Tags