1 /*
2 * Copyright 2002-2008 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;
20 import java.lang.reflect.Constructor;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Modifier;
24 import java.security.AccessControlContext;
25 import java.security.AccessController;
26 import java.security.PrivilegedAction;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.LinkedHashSet;
33 import java.util.LinkedList;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Set;
37 import java.util.TreeSet;
38
39 import org.springframework.beans.BeanUtils;
40 import org.springframework.beans.BeanWrapper;
41 import org.springframework.beans.BeanWrapperImpl;
42 import org.springframework.beans.BeansException;
43 import org.springframework.beans.MutablePropertyValues;
44 import org.springframework.beans.PropertyAccessorUtils;
45 import org.springframework.beans.PropertyValue;
46 import org.springframework.beans.PropertyValues;
47 import org.springframework.beans.TypeConverter;
48 import org.springframework.beans.factory.BeanClassLoaderAware;
49 import org.springframework.beans.factory.BeanCreationException;
50 import org.springframework.beans.factory.BeanCurrentlyInCreationException;
51 import org.springframework.beans.factory.BeanDefinitionStoreException;
52 import org.springframework.beans.factory.BeanFactory;
53 import org.springframework.beans.factory.BeanFactoryAware;
54 import org.springframework.beans.factory.BeanNameAware;
55 import org.springframework.beans.factory.FactoryBean;
56 import org.springframework.beans.factory.InitializingBean;
57 import org.springframework.beans.factory.ObjectFactory;
58 import org.springframework.beans.factory.UnsatisfiedDependencyException;
59 import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
60 import org.springframework.beans.factory.config.BeanDefinition;
61 import org.springframework.beans.factory.config.BeanPostProcessor;
62 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
63 import org.springframework.beans.factory.config.DependencyDescriptor;
64 import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
65 import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
66 import org.springframework.beans.factory.config.TypedStringValue;
67 import org.springframework.core.CollectionFactory;
68 import org.springframework.core.MethodParameter;
69 import org.springframework.core.PriorityOrdered;
70 import org.springframework.util.ClassUtils;
71 import org.springframework.util.ObjectUtils;
72 import org.springframework.util.ReflectionUtils;
73 import org.springframework.util.StringUtils;
74
75 /**
76 * Abstract bean factory superclass that implements default bean creation,
77 * with the full capabilities specified by the {@link RootBeanDefinition} class.
78 * Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
79 * interface in addition to AbstractBeanFactory's {@link #createBean} method.
80 *
81 * <p>Provides bean creation (with constructor resolution), property population,
82 * wiring (including autowiring), and initialization. Handles runtime bean
83 * references, resolves managed collections, calls initialization methods, etc.
84 * Supports autowiring constructors, properties by name, and properties by type.
85 *
86 * <p>The main template method to be implemented by subclasses is
87 * {@link #resolveDependency(DependencyDescriptor, String, Set, TypeConverter)},
88 * used for autowiring by type. In case of a factory which is capable of searching
89 * its bean definitions, matching beans will typically be implemented through such
90 * a search. For other factory styles, simplified matching algorithms can be implemented.
91 *
92 * <p>Note that this class does <i>not</i> assume or implement bean definition
93 * registry capabilities. See {@link DefaultListableBeanFactory} for an implementation
94 * of the {@link org.springframework.beans.factory.ListableBeanFactory} and
95 * {@link BeanDefinitionRegistry} interfaces, which represent the API and SPI
96 * view of such a factory, respectively.
97 *
98 * @author Rod Johnson
99 * @author Juergen Hoeller
100 * @author Rob Harrop
101 * @author Mark Fisher
102 * @since 13.02.2004
103 * @see RootBeanDefinition
104 * @see DefaultListableBeanFactory
105 * @see BeanDefinitionRegistry
106 */
107 public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
108 implements AutowireCapableBeanFactory {
109
110 private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
111
112 /** Whether to automatically try to resolve circular references between beans */
113 private boolean allowCircularReferences = true;
114
115 /**
116 * Whether to resort to injecting a raw bean instance in case of circular reference,
117 * even if the injected bean eventually got wrapped.
118 */
119 private boolean allowRawInjectionDespiteWrapping = false;
120
121 /**
122 * Dependency types to ignore on dependency check and autowire, as Set of
123 * Class objects: for example, String. Default is none.
124 */
125 private final Set ignoredDependencyTypes = new HashSet();
126
127 /**
128 * Dependency interfaces to ignore on dependency check and autowire, as Set of
129 * Class objects. By default, only the BeanFactory interface is ignored.
130 */
131 private final Set ignoredDependencyInterfaces = new HashSet();
132
133 /** Cache of unfinished FactoryBean instances: FactoryBean name --> BeanWrapper */
134 private final Map factoryBeanInstanceCache = CollectionFactory.createConcurrentMapIfPossible(16);
135
136 /** Cache of filtered PropertyDescriptors: bean Class -> PropertyDescriptor array */
137 private final Map filteredPropertyDescriptorsCache = new HashMap();
138
139
140 /**
141 * Create a new AbstractAutowireCapableBeanFactory.
142 */
143 public AbstractAutowireCapableBeanFactory() {
144 super();
145 ignoreDependencyInterface(BeanNameAware.class);
146 ignoreDependencyInterface(BeanFactoryAware.class);
147 ignoreDependencyInterface(BeanClassLoaderAware.class);
148 }
149
150 /**
151 * Create a new AbstractAutowireCapableBeanFactory with the given parent.
152 * @param parentBeanFactory parent bean factory, or <code>null</code> if none
153 */
154 public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
155 this();
156 setParentBeanFactory(parentBeanFactory);
157 }
158
159
160 /**
161 * Set the instantiation strategy to use for creating bean instances.
162 * Default is CglibSubclassingInstantiationStrategy.
163 * @see CglibSubclassingInstantiationStrategy
164 */
165 public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
166 this.instantiationStrategy = instantiationStrategy;
167 }
168
169 /**
170 * Return the instantiation strategy to use for creating bean instances.
171 */
172 protected InstantiationStrategy getInstantiationStrategy() {
173 return this.instantiationStrategy;
174 }
175
176 /**
177 * Set whether to allow circular references between beans - and automatically
178 * try to resolve them.
179 * <p>Note that circular reference resolution means that one of the involved beans
180 * will receive a reference to another bean that is not fully initialized yet.
181 * This can lead to subtle and not-so-subtle side effects on initialization;
182 * it does work fine for many scenarios, though.
183 * <p>Default is "true". Turn this off to throw an exception when encountering
184 * a circular reference, disallowing them completely.
185 * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
186 * between your beans. Refactor your application logic to have the two beans
187 * involved delegate to a third bean that encapsulates their common logic.
188 */
189 public void setAllowCircularReferences(boolean allowCircularReferences) {
190 this.allowCircularReferences = allowCircularReferences;
191 }
192
193 /**
194 * Set whether to allow the raw injection of a bean instance into some other
195 * bean's property, despite the injected bean eventually getting wrapped
196 * (for example, through AOP auto-proxying).
197 * <p>This will only be used as a last resort in case of a circular reference
198 * that cannot be resolved otherwise: essentially, preferring a raw instance
199 * getting injected over a failure of the entire bean wiring process.
200 * <p>Default is "false", as of Spring 2.0. Turn this on to allow for non-wrapped
201 * raw beans injected into some of your references, which was Spring 1.2's
202 * (arguably unclean) default behavior.
203 * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
204 * between your beans, in particular with auto-proxying involved.
205 * @see #setAllowCircularReferences
206 */
207 public void setAllowRawInjectionDespiteWrapping(boolean allowRawInjectionDespiteWrapping) {
208 this.allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping;
209 }
210
211 /**
212 * Ignore the given dependency type for autowiring:
213 * for example, String. Default is none.
214 */
215 public void ignoreDependencyType(Class type) {
216 this.ignoredDependencyTypes.add(type);
217 }
218
219 /**
220 * Ignore the given dependency interface for autowiring.
221 * <p>This will typically be used by application contexts to register
222 * dependencies that are resolved in other ways, like BeanFactory through
223 * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
224 * <p>By default, only the BeanFactoryAware interface is ignored.
225 * For further types to ignore, invoke this method for each type.
226 * @see org.springframework.beans.factory.BeanFactoryAware
227 * @see org.springframework.context.ApplicationContextAware
228 */
229 public void ignoreDependencyInterface(Class ifc) {
230 this.ignoredDependencyInterfaces.add(ifc);
231 }
232
233
234 public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
235 super.copyConfigurationFrom(otherFactory);
236 if (otherFactory instanceof AbstractAutowireCapableBeanFactory) {
237 AbstractAutowireCapableBeanFactory otherAutowireFactory =
238 (AbstractAutowireCapableBeanFactory) otherFactory;
239 this.instantiationStrategy = otherAutowireFactory.instantiationStrategy;
240 this.allowCircularReferences = otherAutowireFactory.allowCircularReferences;
241 this.ignoredDependencyTypes.addAll(otherAutowireFactory.ignoredDependencyTypes);
242 this.ignoredDependencyInterfaces.addAll(otherAutowireFactory.ignoredDependencyInterfaces);
243 }
244 }
245
246
247 //-------------------------------------------------------------------------
248 // Typical methods for creating and populating external bean instances
249 //-------------------------------------------------------------------------
250
251 public Object createBean(Class beanClass) throws BeansException {
252 // Use prototype bean definition, to avoid registering bean as dependent bean.
253 RootBeanDefinition bd = new RootBeanDefinition(beanClass);
254 bd.setScope(SCOPE_PROTOTYPE);
255 return createBean(beanClass.getName(), bd, null);
256 }
257
258 public void autowireBean(Object existingBean) {
259 // Use non-singleton bean definition, to avoid registering bean as dependent bean.
260 RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean));
261 bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
262 BeanWrapper bw = new BeanWrapperImpl(existingBean);
263 initBeanWrapper(bw);
264 populateBean(bd.getBeanClass().getName(), bd, bw);
265 }
266
267 public Object configureBean(Object existingBean, String beanName) throws BeansException {
268 markBeanAsCreated(beanName);
269 BeanDefinition mbd = getMergedBeanDefinition(beanName);
270 RootBeanDefinition bd = null;
271 if (mbd instanceof RootBeanDefinition) {
272 RootBeanDefinition rbd = (RootBeanDefinition) mbd;
273 if (SCOPE_PROTOTYPE.equals(rbd.getScope())) {
274 bd = rbd;
275 }
276 }
277 if (bd == null) {
278 bd = new RootBeanDefinition(mbd);
279 bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
280 }
281 BeanWrapper bw = new BeanWrapperImpl(existingBean);
282 initBeanWrapper(bw);
283 populateBean(beanName, bd, bw);
284 return initializeBean(beanName, existingBean, bd);
285 }
286
287 public Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException {
288 return resolveDependency(descriptor, beanName, null, null);
289 }
290
291
292 //-------------------------------------------------------------------------
293 // Specialized methods for fine-grained control over the bean lifecycle
294 //-------------------------------------------------------------------------
295
296 public Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
297 // Use non-singleton bean definition, to avoid registering bean as dependent bean.
298 RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
299 bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
300 return createBean(beanClass.getName(), bd, null);
301 }
302
303 public Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
304 // Use non-singleton bean definition, to avoid registering bean as dependent bean.
305 RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
306 bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
307 if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
308 return autowireConstructor(beanClass.getName(), bd, null, null).getWrappedInstance();
309 }
310 else {
311 Object bean = getInstantiationStrategy().instantiate(bd, null, this);
312 populateBean(beanClass.getName(), bd, new BeanWrapperImpl(bean));
313 return bean;
314 }
315 }
316
317 public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
318 throws BeansException {
319
320 if (autowireMode == AUTOWIRE_CONSTRUCTOR) {
321 throw new IllegalArgumentException("AUTOWIRE_CONSTRUCTOR not supported for existing bean instance");
322 }
323 // Use non-singleton bean definition, to avoid registering bean as dependent bean.
324 RootBeanDefinition bd =
325 new RootBeanDefinition(ClassUtils.getUserClass(existingBean), autowireMode, dependencyCheck);
326 bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
327 BeanWrapper bw = new BeanWrapperImpl(existingBean);
328 initBeanWrapper(bw);
329 populateBean(bd.getBeanClass().getName(), bd, bw);
330 }
331
332 public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException {
333 markBeanAsCreated(beanName);
334 BeanDefinition bd = getMergedBeanDefinition(beanName);
335 BeanWrapper bw = new BeanWrapperImpl(existingBean);
336 initBeanWrapper(bw);
337 applyPropertyValues(beanName, bd, bw, bd.getPropertyValues());
338 }
339
340 public Object initializeBean(Object existingBean, String beanName) {
341 return initializeBean(beanName, existingBean, null);
342 }
343
344 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
345 throws BeansException {
346
347 Object result = existingBean;
348 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
349 BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
350 result = beanProcessor.postProcessBeforeInitialization(result, beanName);
351 }
352 return result;
353 }
354
355 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
356 throws BeansException {
357
358 Object result = existingBean;
359 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
360 BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
361 result = beanProcessor.postProcessAfterInitialization(result, beanName);
362 }
363 return result;
364 }
365
366
367 //---------------------------------------------------------------------
368 // Implementation of relevant AbstractBeanFactory template methods
369 //---------------------------------------------------------------------
370
371 /**
372 * Central method of this class: creates a bean instance,
373 * populates the bean instance, applies post-processors, etc.
374 * @see #doCreateBean
375 */
376 protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
377 throws BeanCreationException {
378
379 AccessControlContext acc = AccessController.getContext();
380 return AccessController.doPrivileged(new PrivilegedAction() {
381 public Object run() {
382 if (logger.isDebugEnabled()) {
383 logger.debug("Creating instance of bean '" + beanName + "'");
384 }
385 // Make sure bean class is actually resolved at this point.
386 resolveBeanClass(mbd, beanName);
387
388 // Prepare method overrides.
389 try {
390 mbd.prepareMethodOverrides();
391 }
392 catch (BeanDefinitionValidationException ex) {
393 throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
394 beanName, "Validation of method overrides failed", ex);
395 }
396
397 try {
398 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
399 Object bean = resolveBeforeInstantiation(beanName, mbd);
400 if (bean != null) {
401 return bean;
402 }
403 }
404 catch (Throwable ex) {
405 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
406 "BeanPostProcessor before instantiation of bean failed", ex);
407 }
408
409 Object beanInstance = doCreateBean(beanName, mbd, args);
410 if (logger.isDebugEnabled()) {
411 logger.debug("Finished creating instance of bean '" + beanName + "'");
412 }
413 return beanInstance;
414 }
415 }, acc);
416 }
417
418 /**
419 * Actually create the specified bean. Pre-creation processing has already happened
420 * at this point, e.g. checking <code>postProcessBeforeInstantiation</code> callbacks.
421 * <p>Differentiates between default bean instantiation, use of a
422 * factory method, and autowiring a constructor.
423 * @param beanName the name of the bean
424 * @param mbd the merged bean definition for the bean
425 * @param args arguments to use if creating a prototype using explicit arguments to a
426 * static factory method. This parameter must be <code>null</code> except in this case.
427 * @return a new instance of the bean
428 * @throws BeanCreationException if the bean could not be created
429 * @see #instantiateBean
430 * @see #instantiateUsingFactoryMethod
431 * @see #autowireConstructor
432 */
433 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
434 // Instantiate the bean.
435 BeanWrapper instanceWrapper = null;
436 if (mbd.isSingleton()) {
437 instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
438 }
439 if (instanceWrapper == null) {
440 instanceWrapper = createBeanInstance(beanName, mbd, args);
441 }
442 final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
443 Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
444
445 // Allow post-processors to modify the merged bean definition.
446 synchronized (mbd.postProcessingLock) {
447 if (!mbd.postProcessed) {
448 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
449 mbd.postProcessed = true;
450 }
451 }
452
453 // Eagerly cache singletons to be able to resolve circular references
454 // even when triggered by lifecycle interfaces like BeanFactoryAware.
455 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
456 isSingletonCurrentlyInCreation(beanName));
457 if (earlySingletonExposure) {
458 if (logger.isDebugEnabled()) {
459 logger.debug("Eagerly caching bean '" + beanName +
460 "' to allow for resolving potential circular references");
461 }
462 addSingletonFactory(beanName, new ObjectFactory() {
463 public Object getObject() throws BeansException {
464 return getEarlyBeanReference(beanName, mbd, bean);
465 }
466 });
467 }
468
469 // Initialize the bean instance.
470 Object exposedObject = bean;
471 try {
472 populateBean(beanName, mbd, instanceWrapper);
473 exposedObject = initializeBean(beanName, exposedObject, mbd);
474 }
475 catch (Throwable ex) {
476 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
477 throw (BeanCreationException) ex;
478 }
479 else {
480 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
481 }
482 }
483
484 if (earlySingletonExposure) {
485 Object earlySingletonReference = getSingleton(beanName, false);
486 if (earlySingletonReference != null) {
487 if (exposedObject == bean) {
488 exposedObject = earlySingletonReference;
489 }
490 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
491 String[] dependentBeans = getDependentBeans(beanName);
492 Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
493 for (int i = 0; i < dependentBeans.length; i++) {
494 String dependentBean = dependentBeans[i];
495 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
496 actualDependentBeans.add(dependentBean);
497 }
498 }
499 if (!actualDependentBeans.isEmpty()) {
500 throw new BeanCurrentlyInCreationException(beanName,
501 "Bean with name '" + beanName + "' has been injected into other beans [" +
502 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
503 "] in its raw version as part of a circular reference, but has eventually been " +
504 "wrapped. This means that said other beans do not use the final version of the " +
505 "bean. This is often the result of over-eager type matching - consider using " +
506 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
507 }
508 }
509 }
510 }
511
512 // Register bean as disposable.
513 registerDisposableBeanIfNecessary(beanName, bean, mbd);
514
515 return exposedObject;
516 }
517
518 protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
519 Class beanClass = null;
520 if (mbd.getFactoryMethodName() != null) {
521 beanClass = getTypeForFactoryMethod(beanName, mbd, typesToMatch);
522 }
523 else {
524 beanClass = resolveBeanClass(mbd, beanName, typesToMatch);
525 }
526 // Apply SmartInstantiationAwareBeanPostProcessors to predict the
527 // eventual type after a before-instantiation shortcut.
528 if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
529 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
530 BeanPostProcessor bp = (BeanPostProcessor) it.next();
531 if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
532 SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
533 Class processedType = ibp.predictBeanType(beanClass, beanName);
534 if (processedType != null) {
535 return processedType;
536 }
537 }
538 }
539 }
540 return beanClass;
541 }
542
543 /**
544 * Determine the bean type for the given bean definition which is based on
545 * a factory method. Only called if there is no singleton instance registered
546 * for the target bean already.
547 * <p>This implementation determines the type matching {@link #createBean}'s
548 * different creation strategies. As far as possible, we'll perform static
549 * type checking to avoid creation of the target bean.
550 * @param beanName the name of the bean (for error handling purposes)
551 * @param mbd the merged bean definition for the bean
552 * @param typesToMatch the types to match in case of internal type matching purposes
553 * (also signals that the returned <code>Class</code> will never be exposed to application code)
554 * @return the type for the bean if determinable, or <code>null</code> else
555 * @see #createBean
556 */
557 protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
558 Class factoryClass = null;
559 boolean isStatic = true;
560
561 String factoryBeanName = mbd.getFactoryBeanName();
562 if (factoryBeanName != null) {
563 if (factoryBeanName.equals(beanName)) {
564 throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
565 "factory-bean reference points back to the same bean definition");
566 }
567 // Check declared factory method return type on factory class.
568 factoryClass = getType(factoryBeanName);
569 isStatic = false;
570 }
571 else {
572 // Check declared factory method return type on bean class.
573 factoryClass = resolveBeanClass(mbd, beanName, typesToMatch);
574 }
575
576 if (factoryClass == null) {
577 return null;
578 }
579
580 // If all factory methods have the same return type, return that type.
581 // Can't clearly figure out exact method due to type converting / autowiring!
582 int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
583 Method[] candidates = ReflectionUtils.getAllDeclaredMethods(factoryClass);
584 Set returnTypes = new HashSet(1);
585 for (int i = 0; i < candidates.length; i++) {
586 Method factoryMethod = candidates[i];
587 if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic &&
588 factoryMethod.getName().equals(mbd.getFactoryMethodName()) &&
589 factoryMethod.getParameterTypes().length >= minNrOfArgs) {
590 returnTypes.add(factoryMethod.getReturnType());
591 }
592 }
593
594 if (returnTypes.size() == 1) {
595 // Clear return type found: all factory methods return same type.
596 return (Class) returnTypes.iterator().next();
597 }
598 else {
599 // Ambiguous return types found: return null to indicate "not determinable".
600 return null;
601 }
602 }
603
604 /**
605 * This implementation checks the FactoryBean's <code>getObjectType</code> method
606 * on a plain instance of the FactoryBean, without bean properties applied yet.
607 * If this doesn't return a type yet, a full creation of the FactoryBean is
608 * used as fallback (through delegation to the superclass's implementation).
609 * <p>The shortcut check for a FactoryBean is only applied in case of a singleton
610 * FactoryBean. If the FactoryBean instance itself is not kept as singleton,
611 * it will be fully created to check the type of its exposed object.
612 */
613 protected Class getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
614 FactoryBean fb = (mbd.isSingleton() ?
615 getSingletonFactoryBeanForTypeCheck(beanName, mbd) :
616 getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
617
618 if (fb != null) {
619 // Try to obtain the FactoryBean's object type from this early stage of the instance.
620 Class objectType = getTypeForFactoryBean(fb);
621 if (objectType != null) {
622 return objectType;
623 }
624 }
625
626 // No type found - fall back to full creation of the FactoryBean instance.
627 return super.getTypeForFactoryBean(beanName, mbd);
628 }
629
630 /**
631 * Obtain a reference for early access to the specified bean,
632 * typically for the purpose of resolving a circular reference.
633 * @param beanName the name of the bean (for error handling purposes)
634 * @param mbd the merged bean definition for the bean
635 * @param bean the raw bean instance
636 * @return the object to expose as bean reference
637 */
638 protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
639 Object exposedObject = bean;
640 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
641 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
642 BeanPostProcessor bp = (BeanPostProcessor) it.next();
643 if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
644 SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
645 exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
646 }
647 }
648 }
649 return exposedObject;
650 }
651
652
653 //---------------------------------------------------------------------
654 // Implementation methods
655 //---------------------------------------------------------------------
656
657 /**
658 * Obtain a "shortcut" singleton FactoryBean instance to use for a
659 * <code>getObjectType()</code> call, without full initialization
660 * of the FactoryBean.
661 * @param beanName the name of the bean
662 * @param mbd the bean definition for the bean
663 * @return the FactoryBean instance, or <code>null</code> to indicate
664 * that we couldn't obtain a shortcut FactoryBean instance
665 */
666 private FactoryBean getSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
667 synchronized (getSingletonMutex()) {
668 BeanWrapper bw = (BeanWrapper) this.factoryBeanInstanceCache.get(beanName);
669 if (bw != null) {
670 return (FactoryBean) bw.getWrappedInstance();
671 }
672 if (isSingletonCurrentlyInCreation(beanName)) {
673 return null;
674 }
675 Object instance = null;
676 try {
677 // Mark this bean as currently in creation, even if just partially.
678 beforeSingletonCreation(beanName);
679 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
680 instance = resolveBeforeInstantiation(beanName, mbd);
681 if (instance == null) {
682 bw = createBeanInstance(beanName, mbd, null);
683 instance = bw.getWrappedInstance();
684 }
685 }
686 finally {
687 // Finished partial creation of this bean.
688 afterSingletonCreation(beanName);
689 }
690 FactoryBean fb = getFactoryBean(beanName, instance);
691 if (bw != null) {
692 this.factoryBeanInstanceCache.put(beanName, bw);
693 }
694 return fb;
695 }
696 }
697
698 /**
699 * Obtain a "shortcut" non-singleton FactoryBean instance to use for a
700 * <code>getObjectType()</code> call, without full initialization
701 * of the FactoryBean.
702 * @param beanName the name of the bean
703 * @param mbd the bean definition for the bean
704 * @return the FactoryBean instance, or <code>null</code> to indicate
705 * that we couldn't obtain a shortcut FactoryBean instance
706 */
707 private FactoryBean getNonSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) {
708 if (isPrototypeCurrentlyInCreation(beanName)) {
709 return null;
710 }
711 Object instance = null;
712 try {
713 // Mark this bean as currently in creation, even if just partially.
714 beforePrototypeCreation(beanName);
715 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
716 instance = resolveBeforeInstantiation(beanName, mbd);
717 if (instance == null) {
718 BeanWrapper bw = createBeanInstance(beanName, mbd, null);
719 instance = bw.getWrappedInstance();
720 }
721 }
722 finally {
723 // Finished partial creation of this bean.
724 afterPrototypeCreation(beanName);
725 }
726 return getFactoryBean(beanName, instance);
727 }
728
729 /**
730 * Apply MergedBeanDefinitionPostProcessors to the specified bean definition,
731 * invoking their <code>postProcessMergedBeanDefinition</code> methods.
732 * @param mbd the merged bean definition for the bean
733 * @param beanType the actual type of the managed bean instance
734 * @param beanName the name of the bean
735 * @throws BeansException if any post-processing failed
736 * @see MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
737 */
738 protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class beanType, String beanName)
739 throws BeansException {
740
741 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
742 BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
743 if (beanProcessor instanceof MergedBeanDefinitionPostProcessor) {
744 MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) beanProcessor;
745 bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
746 }
747 }
748 }
749
750 /**
751 * Apply before-instantiation post-processors, resolving whether there is a
752 * before-instantiation shortcut for the specified bean.
753 * @param beanName the name of the bean
754 * @param mbd the bean definition for the bean
755 * @return the shortcut-determined bean instance, or <code>null</code> if none
756 */
757 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
758 Object bean = null;
759 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
760 // Make sure bean class is actually resolved at this point.
761 if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
762 bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
763 if (bean != null) {
764 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
765 }
766 }
767 mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);
768 }
769 return bean;
770 }
771
772 /**
773 * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
774 * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods.
775 * <p>Any returned object will be used as the bean instead of actually instantiating
776 * the target bean. A <code>null</code> return value from the post-processor will
777 * result in the target bean being instantiated.
778 * @param beanClass the class of the bean to be instantiated
779 * @param beanName the name of the bean
780 * @return the bean object to use instead of a default instance of the target bean, or <code>null</code>
781 * @throws BeansException if any post-processing failed
782 * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
783 */
784 protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)
785 throws BeansException {
786
787 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
788 BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
789 if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
790 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
791 Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
792 if (result != null) {
793 return result;
794 }
795 }
796 }
797 return null;
798 }
799
800 /**
801 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
802 * factory method, constructor autowiring, or simple instantiation.
803 * @param beanName the name of the bean
804 * @param mbd the bean definition for the bean
805 * @param args arguments to use if creating a prototype using explicit arguments to a
806 * static factory method. It is invalid to use a non-null args value in any other case.
807 * @return BeanWrapper for the new instance
808 * @see #instantiateUsingFactoryMethod
809 * @see #autowireConstructor
810 * @see #instantiateBean
811 */
812 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
813 // Make sure bean class is actually resolved at this point.
814 Class beanClass = resolveBeanClass(mbd, beanName);
815
816 if (mbd.getFactoryMethodName() != null) {
817 return instantiateUsingFactoryMethod(beanName, mbd, args);
818 }
819
820 // Shortcut when re-creating the same bean...
821 if (mbd.resolvedConstructorOrFactoryMethod != null) {
822 if (mbd.constructorArgumentsResolved) {
823 return autowireConstructor(beanName, mbd, null, args);
824 }
825 else {
826 return instantiateBean(beanName, mbd);
827 }
828 }
829
830 // Need to determine the constructor...
831 Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
832 if (ctors != null ||
833 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
834 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
835 return autowireConstructor(beanName, mbd, ctors, args);
836 }
837
838 // No special handling: simply use no-arg constructor.
839 return instantiateBean(beanName, mbd);
840 }
841
842 /**
843 * Determine candidate constructors to use for the given bean, checking all registered
844 * {@link SmartInstantiationAwareBeanPostProcessor SmartInstantiationAwareBeanPostProcessors}.
845 * @param beanClass the raw class of the bean
846 * @param beanName the name of the bean
847 * @return the candidate constructors, or <code>null</code> if none specified
848 * @throws org.springframework.beans.BeansException in case of errors
849 * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
850 */
851 protected Constructor[] determineConstructorsFromBeanPostProcessors(Class beanClass, String beanName)
852 throws BeansException {
853
854 if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
855 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
856 BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
857 if (beanProcessor instanceof SmartInstantiationAwareBeanPostProcessor) {
858 SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) beanProcessor;
859 Constructor[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
860 if (ctors != null) {
861 return ctors;
862 }
863 }
864 }
865 }
866 return null;
867 }
868
869 /**
870 * Instantiate the given bean using its default constructor.
871 * @param beanName the name of the bean
872 * @param mbd the bean definition for the bean
873 * @return BeanWrapper for the new instance
874 */
875 protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
876 try {
877 Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
878 BeanWrapper bw = new BeanWrapperImpl(beanInstance);
879 initBeanWrapper(bw);
880 return bw;
881 }
882 catch (Throwable ex) {
883 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
884 }
885 }
886
887 /**
888 * Instantiate the bean using a named factory method. The method may be static, if the
889 * mbd parameter specifies a class, rather than a factoryBean, or an instance variable
890 * on a factory object itself configured using Dependency Injection.
891 * @param beanName the name of the bean
892 * @param mbd the bean definition for the bean
893 * @param explicitArgs argument values passed in programmatically via the getBean method,
894 * or <code>null</code> if none (-> use constructor argument values from bean definition)
895 * @return BeanWrapper for the new instance
896 * @see #getBean(String, Object[])
897 */
898 protected BeanWrapper instantiateUsingFactoryMethod(
899 String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {
900
901 ConstructorResolver constructorResolver =
902 new ConstructorResolver(this, this, getInstantiationStrategy(), getCustomTypeConverter());
903 return constructorResolver.instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
904 }
905
906 /**
907 * "autowire constructor" (with constructor arguments by type) behavior.
908 * Also applied if explicit constructor argument values are specified,
909 * matching all remaining arguments with beans from the bean factory.
910 * <p>This corresponds to constructor injection: In this mode, a Spring
911 * bean factory is able to host components that expect constructor-based
912 * dependency resolution.
913 * @param beanName the name of the bean
914 * @param mbd the bean definition for the bean
915 * @param ctors the chosen candidate constructors
916 * @param explicitArgs argument values passed in programmatically via the getBean method,
917 * or <code>null</code> if none (-> use constructor argument values from bean definition)
918 * @return BeanWrapper for the new instance
919 */
920 protected BeanWrapper autowireConstructor(
921 String beanName, RootBeanDefinition mbd, Constructor[] ctors, Object[] explicitArgs) {
922
923 ConstructorResolver constructorResolver =
924 new ConstructorResolver(this, this, getInstantiationStrategy(), getCustomTypeConverter());
925 return constructorResolver.autowireConstructor(beanName, mbd, ctors, explicitArgs);
926 }
927
928 /**
929 * Populate the bean instance in the given BeanWrapper with the property values
930 * from the bean definition.
931 * @param beanName the name of the bean
932 * @param mbd the bean definition for the bean
933 * @param bw BeanWrapper with bean instance
934 */
935 protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
936 PropertyValues pvs = mbd.getPropertyValues();
937
938 if (bw == null) {
939 if (!pvs.isEmpty()) {
940 throw new BeanCreationException(
941 mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
942 }
943 else {
944 // Skip property population phase for null instance.
945 return;
946 }
947 }
948
949 // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
950 // state of the bean before properties are set. This can be used, for example,
951 // to support styles of field injection.
952 boolean continueWithPropertyPopulation = true;
953
954 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
955 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
956 BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
957 if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
958 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
959 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
960 continueWithPropertyPopulation = false;
961 break;
962 }
963 }
964 }
965 }
966
967 if (!continueWithPropertyPopulation) {
968 return;
969 }
970
971 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
972 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
973 MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
974
975 // Add property values based on autowire by name if applicable.
976 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
977 autowireByName(beanName, mbd, bw, newPvs);
978 }
979
980 // Add property values based on autowire by type if applicable.
981 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
982 autowireByType(beanName, mbd, bw, newPvs);
983 }
984
985 pvs = newPvs;
986 }
987
988 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
989 boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
990
991 if (hasInstAwareBpps || needsDepCheck) {
992 PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
993 if (hasInstAwareBpps) {
994 for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) {
995 BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
996 if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
997 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
998 pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
999 if (pvs == null) {
1000 return;
1001 }
1002 }
1003 }
1004 }
1005 if (needsDepCheck) {
1006 checkDependencies(beanName, mbd, filteredPds, pvs);
1007 }
1008 }
1009
1010 applyPropertyValues(beanName, mbd, bw, pvs);
1011 }
1012
1013 /**
1014 * Fill in any missing property values with references to
1015 * other beans in this factory if autowire is set to "byName".
1016 * @param beanName the name of the bean we're wiring up.
1017 * Useful for debugging messages; not used functionally.
1018 * @param mbd bean definition to update through autowiring
1019 * @param bw BeanWrapper from which we can obtain information about the bean
1020 * @param pvs the PropertyValues to register wired objects with
1021 */
1022 protected void autowireByName(
1023 String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
1024
1025 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
1026 for (int i = 0; i < propertyNames.length; i++) {
1027 String propertyName = propertyNames[i];
1028 if (containsBean(propertyName)) {
1029 Object bean = getBean(propertyName);
1030 pvs.addPropertyValue(propertyName, bean);
1031 registerDependentBean(propertyName, beanName);
1032 if (logger.isDebugEnabled()) {
1033 logger.debug("Added autowiring by name from bean name '" + beanName +
1034 "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
1035 }
1036 }
1037 else {
1038 if (logger.isTraceEnabled()) {
1039 logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
1040 "' by name: no matching bean found");
1041 }
1042 }
1043 }
1044 }
1045
1046 /**
1047 * Abstract method defining "autowire by type" (bean properties by type) behavior.
1048 * <p>This is like PicoContainer default, in which there must be exactly one bean
1049 * of the property type in the bean factory. This makes bean factories simple to
1050 * configure for small namespaces, but doesn't work as well as standard Spring
1051 * behavior for bigger applications.
1052 * @param beanName the name of the bean to autowire by type
1053 * @param mbd the merged bean definition to update through autowiring
1054 * @param bw BeanWrapper from which we can obtain information about the bean
1055 * @param pvs the PropertyValues to register wired objects with
1056 */
1057 protected void autowireByType(
1058 String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
1059
1060 TypeConverter converter = getCustomTypeConverter();
1061 if (converter == null) {
1062 converter = bw;
1063 }
1064
1065 Set autowiredBeanNames = new LinkedHashSet(4);
1066 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
1067 for (int i = 0; i < propertyNames.length; i++) {
1068 String propertyName = propertyNames[i];
1069 try {
1070 PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
1071 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
1072 // Do not allow eager init for type matching in case of a prioritized post-processor.
1073 boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
1074 DependencyDescriptor desc = new DependencyDescriptor(methodParam, false, eager);
1075
1076 Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
1077 if (autowiredArgument != null) {
1078 pvs.addPropertyValue(propertyName, autowiredArgument);
1079 }
1080 for (Iterator it = autowiredBeanNames.iterator(); it.hasNext();) {
1081 String autowiredBeanName = (String) it.next();
1082 registerDependentBean(autowiredBeanName, beanName);
1083 if (logger.isDebugEnabled()) {
1084 logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
1085 propertyName + "' to bean named '" + autowiredBeanName + "'");
1086 }
1087 }
1088 autowiredBeanNames.clear();
1089 }
1090 catch (BeansException ex) {
1091 throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
1092 }
1093 }
1094 }
1095
1096
1097 /**
1098 * Return an array of non-simple bean properties that are unsatisfied.
1099 * These are probably unsatisfied references to other beans in the
1100 * factory. Does not include simple properties like primitives or Strings.
1101 * @param mbd the merged bean definition the bean was created with
1102 * @param bw the BeanWrapper the bean was created with
1103 * @return an array of bean property names
1104 * @see org.springframework.beans.BeanUtils#isSimpleProperty
1105 */
1106 protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
1107 Set result = new TreeSet();
1108 PropertyValues pvs = mbd.getPropertyValues();
1109 PropertyDescriptor[] pds = bw.getPropertyDescriptors();
1110 for (int i = 0; i < pds.length; i++) {
1111 if (pds[i].getWriteMethod() != null && !isExcludedFromDependencyCheck(pds[i]) &&
1112 !pvs.contains(pds[i].getName()) && !BeanUtils.isSimpleProperty(pds[i].getPropertyType())) {
1113 result.add(pds[i].getName());
1114 }
1115 }
1116 return StringUtils.toStringArray(result);
1117 }
1118
1119 /**
1120 * Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
1121 * excluding ignored dependency types or properties defined on ignored
1122 * dependency interfaces.
1123 * @param bw the BeanWrapper the bean was created with
1124 * @return the filtered PropertyDescriptors
1125 * @see #isExcludedFromDependencyCheck
1126 */
1127 protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
1128 synchronized (this.filteredPropertyDescriptorsCache) {
1129 PropertyDescriptor[] filtered = (PropertyDescriptor[])
1130 this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
1131 if (filtered == null) {
1132 List pds = new LinkedList(Arrays.asList(bw.getPropertyDescriptors()));
1133 for (Iterator it = pds.iterator(); it.hasNext();) {
1134 PropertyDescriptor pd = (PropertyDescriptor) it.next();
1135 if (isExcludedFromDependencyCheck(pd)) {
1136 it.remove();
1137 }
1138 }
1139 filtered = (PropertyDescriptor[]) pds.toArray(new PropertyDescriptor[pds.size()]);
1140 this.filteredPropertyDescriptorsCache.put(bw.getWrappedClass(), filtered);
1141 }
1142 return filtered;
1143 }
1144 }
1145
1146 /**
1147 * Determine whether the given bean property is excluded from dependency checks.
1148 * <p>This implementation excludes properties defined by CGLIB and
1149 * properties whose type matches an ignored dependency type or which
1150 * are defined by an ignored dependency interface.
1151 * @param pd the PropertyDescriptor of the bean property
1152 * @return whether the bean property is excluded
1153 * @see #ignoreDependencyType(Class)
1154 * @see #ignoreDependencyInterface(Class)
1155 */
1156 protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
1157 return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
1158 this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
1159 AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
1160 }
1161
1162 /**
1163 * Perform a dependency check that all properties exposed have been set,
1164 * if desired. Dependency checks can be objects (collaborating beans),
1165 * simple (primitives and String), or all (both).
1166 * @param beanName the name of the bean
1167 * @param mbd the merged bean definition the bean was created with
1168 * @param pds the relevant property descriptors for the target bean
1169 * @param pvs the property values to be applied to the bean
1170 * @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor)
1171 */
1172 protected void checkDependencies(
1173 String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs)
1174 throws UnsatisfiedDependencyException {
1175
1176 int dependencyCheck = mbd.getDependencyCheck();
1177 for (int i = 0; i < pds.length; i++) {
1178 if (pds[i].getWriteMethod() != null && !pvs.contains(pds[i].getName())) {
1179 boolean isSimple = BeanUtils.isSimpleProperty(pds[i].getPropertyType());
1180 boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
1181 (isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
1182 (!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
1183 if (unsatisfied) {
1184 throw new UnsatisfiedDependencyException(
1185 mbd.getResourceDescription(), beanName, pds[i].getName(),
1186 "Set this property value or disable dependency checking for this bean.");
1187 }
1188 }
1189 }
1190 }
1191
1192 /**
1193 * Apply the given property values, resolving any runtime references
1194 * to other beans in this bean factory. Must use deep copy, so we
1195 * don't permanently modify this property.
1196 * @param beanName the bean name passed for better exception information
1197 * @param mbd the merged bean definition
1198 * @param bw the BeanWrapper wrapping the target object
1199 * @param pvs the new property values
1200 */
1201 protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
1202 if (pvs == null || pvs.isEmpty()) {
1203 return;
1204 }
1205
1206 MutablePropertyValues mpvs = null;
1207 List original = null;
1208
1209 if (pvs instanceof MutablePropertyValues) {
1210 mpvs = (MutablePropertyValues) pvs;
1211 if (mpvs.isConverted()) {
1212 // Shortcut: use the pre-converted values as-is.
1213 try {
1214 bw.setPropertyValues(mpvs);
1215 return;
1216 }
1217 catch (BeansException ex) {
1218 throw new BeanCreationException(
1219 mbd.getResourceDescription(), beanName, "Error setting property values", ex);
1220 }
1221 }
1222 original = mpvs.getPropertyValueList();
1223 }
1224 else {
1225 original = Arrays.asList(pvs.getPropertyValues());
1226 }
1227
1228 TypeConverter converter = getCustomTypeConverter();
1229 if (converter == null) {
1230 converter = bw;
1231 }
1232 BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
1233
1234 // Create a deep copy, resolving any references for values.
1235 List deepCopy = new ArrayList(original.size());
1236 boolean resolveNecessary = false;
1237 for (Iterator it = original.iterator(); it.hasNext();) {
1238 PropertyValue pv = (PropertyValue) it.next();
1239 if (pv.isConverted()) {
1240 deepCopy.add(pv);
1241 }
1242 else {
1243 String propertyName = pv.getName();
1244 Object originalValue = pv.getValue();
1245 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
1246 Object convertedValue = resolvedValue;
1247 boolean convertible = bw.isWritableProperty(propertyName) &&
1248 !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
1249 if (convertible) {
1250 convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
1251 }
1252 // Possibly store converted value in merged bean definition,
1253 // in order to avoid re-conversion for every created bean instance.
1254 if (resolvedValue == originalValue) {
1255 if (convertible) {
1256 pv.setConvertedValue(convertedValue);
1257 }
1258 deepCopy.add(pv);
1259 }
1260 else if (originalValue instanceof TypedStringValue && convertible) {
1261 pv.setConvertedValue(convertedValue);
1262 deepCopy.add(pv);
1263 }
1264 else {
1265 resolveNecessary = true;
1266 deepCopy.add(new PropertyValue(pv, convertedValue));
1267 }
1268 }
1269 }
1270 if (mpvs != null && !resolveNecessary) {
1271 mpvs.setConverted();
1272 }
1273
1274 // Set our (possibly massaged) deep copy.
1275 try {
1276 bw.setPropertyValues(new MutablePropertyValues(deepCopy));
1277 }
1278 catch (BeansException ex) {
1279 throw new BeanCreationException(
1280 mbd.getResourceDescription(), beanName, "Error setting property values", ex);
1281 }
1282 }
1283
1284 /**
1285 * Convert the given value for the specified target property.
1286 */
1287 private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
1288 if (converter instanceof BeanWrapperImpl) {
1289 return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
1290 }
1291 else {
1292 PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
1293 MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
1294 return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
1295 }
1296 }
1297
1298
1299 /**
1300 * Initialize the given bean instance, applying factory callbacks
1301 * as well as init methods and bean post processors.
1302 * <p>Called from {@link #createBean} for traditionally defined beans,
1303 * and from {@link #initializeBean} for existing bean instances.
1304 * @param beanName the bean name in the factory (for debugging purposes)
1305 * @param bean the new bean instance we may need to initialize
1306 * @param mbd the bean definition that the bean was created with
1307 * (can also be <code>null</code>, if given an existing bean instance)
1308 * @return the initialized bean instance (potentially wrapped)
1309 * @see BeanNameAware
1310 * @see BeanClassLoaderAware
1311 * @see BeanFactoryAware
1312 * @see #applyBeanPostProcessorsBeforeInitialization
1313 * @see #invokeInitMethods
1314 * @see #applyBeanPostProcessorsAfterInitialization
1315 */
1316 protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
1317 if (bean instanceof BeanNameAware) {
1318 ((BeanNameAware) bean).setBeanName(beanName);
1319 }
1320
1321 if (bean instanceof BeanClassLoaderAware) {
1322 ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
1323 }
1324
1325 if (bean instanceof BeanFactoryAware) {
1326 ((BeanFactoryAware) bean).setBeanFactory(this);
1327 }
1328
1329 Object wrappedBean = bean;
1330 if (mbd == null || !mbd.isSynthetic()) {
1331 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
1332 }
1333
1334 try {
1335 invokeInitMethods(beanName, wrappedBean, mbd);
1336 }
1337 catch (Throwable ex) {
1338 throw new BeanCreationException(
1339 (mbd != null ? mbd.getResourceDescription() : null),
1340 beanName, "Invocation of init method failed", ex);
1341 }
1342
1343 if (mbd == null || !mbd.isSynthetic()) {
1344 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
1345 }
1346 return wrappedBean;
1347 }
1348
1349 /**
1350 * Give a bean a chance to react now all its properties are set,
1351 * and a chance to know about its owning bean factory (this object).
1352 * This means checking whether the bean implements InitializingBean or defines
1353 * a custom init method, and invoking the necessary callback(s) if it does.
1354 * @param beanName the bean name in the factory (for debugging purposes)
1355 * @param bean the new bean instance we may need to initialize
1356 * @param mbd the merged bean definition that the bean was created with
1357 * (can also be <code>null</code>, if given an existing bean instance)
1358 * @throws Throwable if thrown by init methods or by the invocation process
1359 * @see #invokeCustomInitMethod
1360 */
1361 protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
1362 throws Throwable {
1363
1364 boolean isInitializingBean = (bean instanceof InitializingBean);
1365 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
1366 if (logger.isDebugEnabled()) {
1367 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
1368 }
1369 ((InitializingBean) bean).afterPropertiesSet();
1370 }
1371
1372 String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);
1373 if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
1374 !mbd.isExternallyManagedInitMethod(initMethodName)) {
1375 invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());
1376 }
1377 }
1378
1379 /**
1380 * Invoke the specified custom init method on the given bean.
1381 * Called by invokeInitMethods.
1382 * <p>Can be overridden in subclasses for custom resolution of init
1383 * methods with arguments.
1384 * @param beanName the bean name in the factory (for debugging purposes)
1385 * @param bean the new bean instance we may need to initialize
1386 * @param initMethodName the name of the custom init method
1387 * @param enforceInitMethod indicates whether the defined init method needs to exist
1388 * @see #invokeInitMethods
1389 */
1390 protected void invokeCustomInitMethod(
1391 String beanName, Object bean, String initMethodName, boolean enforceInitMethod) throws Throwable {
1392
1393 Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);
1394 if (initMethod == null) {
1395 if (enforceInitMethod) {
1396 throw new NoSuchMethodException("Couldn't find an init method named '" + initMethodName +
1397 "' on bean with name '" + beanName + "'");
1398 }
1399 else {
1400 if (logger.isDebugEnabled()) {
1401 logger.debug("No default init method named '" + initMethodName +
1402 "' found on bean with name '" + beanName + "'");
1403 }
1404 // Ignore non-existent default lifecycle methods.
1405 return;
1406 }
1407 }
1408
1409 if (logger.isDebugEnabled()) {
1410 logger.debug("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'");
1411 }
1412 ReflectionUtils.makeAccessible(initMethod);
1413 try {
1414 initMethod.invoke(bean, (Object[]) null);
1415 }
1416 catch (InvocationTargetException ex) {
1417 throw ex.getTargetException();
1418 }
1419 }
1420
1421
1422 /**
1423 * Applies the <code>postProcessAfterInitialization</code> callback of all
1424 * registered BeanPostProcessors, giving them a chance to post-process the
1425 * object obtained from FactoryBeans (for example, to auto-proxy them).
1426 * @see #applyBeanPostProcessorsAfterInitialization
1427 */
1428 protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
1429 return applyBeanPostProcessorsAfterInitialization(object, beanName);
1430 }
1431
1432 /**
1433 * Overridden to clear FactoryBean instance cache as well.
1434 */
1435 protected void removeSingleton(String beanName) {
1436 super.removeSingleton(beanName);
1437 this.factoryBeanInstanceCache.remove(beanName);
1438 }
1439
1440 }