0001: /*
0002: * Copyright 2002-2007 the original author or authors.
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016:
0017: package org.springframework.beans.factory.support;
0018:
0019: import java.beans.PropertyDescriptor;
0020: import java.lang.reflect.Constructor;
0021: import java.lang.reflect.InvocationTargetException;
0022: import java.lang.reflect.Method;
0023: import java.lang.reflect.Modifier;
0024: import java.util.ArrayList;
0025: import java.util.Arrays;
0026: import java.util.Collections;
0027: import java.util.HashMap;
0028: import java.util.HashSet;
0029: import java.util.Iterator;
0030: import java.util.LinkedList;
0031: import java.util.List;
0032: import java.util.Map;
0033: import java.util.Set;
0034: import java.util.TreeSet;
0035:
0036: import org.springframework.beans.BeanUtils;
0037: import org.springframework.beans.BeanWrapper;
0038: import org.springframework.beans.BeanWrapperImpl;
0039: import org.springframework.beans.BeansException;
0040: import org.springframework.beans.FatalBeanException;
0041: import org.springframework.beans.MutablePropertyValues;
0042: import org.springframework.beans.PropertyAccessorUtils;
0043: import org.springframework.beans.PropertyValue;
0044: import org.springframework.beans.PropertyValues;
0045: import org.springframework.beans.factory.BeanClassLoaderAware;
0046: import org.springframework.beans.factory.BeanCreationException;
0047: import org.springframework.beans.factory.BeanCurrentlyInCreationException;
0048: import org.springframework.beans.factory.BeanDefinitionStoreException;
0049: import org.springframework.beans.factory.BeanFactory;
0050: import org.springframework.beans.factory.BeanFactoryAware;
0051: import org.springframework.beans.factory.BeanNameAware;
0052: import org.springframework.beans.factory.FactoryBean;
0053: import org.springframework.beans.factory.InitializingBean;
0054: import org.springframework.beans.factory.UnsatisfiedDependencyException;
0055: import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
0056: import org.springframework.beans.factory.config.BeanPostProcessor;
0057: import org.springframework.beans.factory.config.ConfigurableBeanFactory;
0058: import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
0059: import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
0060: import org.springframework.beans.factory.config.TypedStringValue;
0061: import org.springframework.util.ReflectionUtils;
0062: import org.springframework.util.StringUtils;
0063:
0064: /**
0065: * Abstract bean factory superclass that implements default bean creation,
0066: * with the full capabilities specified by the {@link RootBeanDefinition} class.
0067: * Implements the {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}
0068: * interface in addition to AbstractBeanFactory's {@link #createBean} method.
0069: *
0070: * <p>Provides bean creation (with constructor resolution), property population,
0071: * wiring (including autowiring), and initialization. Handles runtime bean
0072: * references, resolves managed collections, calls initialization methods, etc.
0073: * Supports autowiring constructors, properties by name, and properties by type.
0074: *
0075: * <p>The main template method to be implemented by subclasses is
0076: * {@link #findAutowireCandidates}, used for autowiring by type. In case of
0077: * a factory which is capable of searching its bean definitions, matching
0078: * beans will typically be implemented through such a search. For other
0079: * factory styles, simplified matching algorithms can be implemented.
0080: *
0081: * <p>Note that this class does <i>not</i> assume or implement bean definition
0082: * registry capabilities. See {@link DefaultListableBeanFactory} for an implementation
0083: * of the {@link org.springframework.beans.factory.ListableBeanFactory} and
0084: * {@link BeanDefinitionRegistry} interfaces, which represent the API and SPI
0085: * view of such a factory, respectively.
0086: *
0087: * @author Rod Johnson
0088: * @author Juergen Hoeller
0089: * @author Rob Harrop
0090: * @since 13.02.2004
0091: * @see RootBeanDefinition
0092: * @see DefaultListableBeanFactory
0093: * @see BeanDefinitionRegistry
0094: */
0095: public abstract class AbstractAutowireCapableBeanFactory extends
0096: AbstractBeanFactory implements AutowireCapableBeanFactory {
0097:
0098: private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
0099:
0100: /** Whether to automatically try to resolve circular references between beans */
0101: private boolean allowCircularReferences = true;
0102:
0103: /**
0104: * Whether to resort to injecting a raw bean instance in case of circular reference,
0105: * even if the injected bean eventually got wrapped.
0106: */
0107: private boolean allowRawInjectionDespiteWrapping = false;
0108:
0109: /**
0110: * Dependency types to ignore on dependency check and autowire, as Set of
0111: * Class objects: for example, String. Default is none.
0112: */
0113: private final Set ignoredDependencyTypes = new HashSet();
0114:
0115: /**
0116: * Dependency interfaces to ignore on dependency check and autowire, as Set of
0117: * Class objects. By default, only the BeanFactory interface is ignored.
0118: */
0119: private final Set ignoredDependencyInterfaces = new HashSet();
0120:
0121: /** Cache of unfinished FactoryBean instances: FactoryBean name --> BeanWrapper */
0122: private final Map factoryBeanInstanceCache = new HashMap();
0123:
0124: /** Cache of filtered PropertyDescriptors: bean Class -> PropertyDescriptor array */
0125: private final Map filteredPropertyDescriptorsCache = new HashMap();
0126:
0127: /**
0128: * Create a new AbstractAutowireCapableBeanFactory.
0129: */
0130: public AbstractAutowireCapableBeanFactory() {
0131: super ();
0132: ignoreDependencyInterface(BeanNameAware.class);
0133: ignoreDependencyInterface(BeanFactoryAware.class);
0134: ignoreDependencyInterface(BeanClassLoaderAware.class);
0135: }
0136:
0137: /**
0138: * Create a new AbstractAutowireCapableBeanFactory with the given parent.
0139: * @param parentBeanFactory parent bean factory, or <code>null</code> if none
0140: */
0141: public AbstractAutowireCapableBeanFactory(
0142: BeanFactory parentBeanFactory) {
0143: this ();
0144: setParentBeanFactory(parentBeanFactory);
0145: }
0146:
0147: /**
0148: * Set the instantiation strategy to use for creating bean instances.
0149: * Default is CglibSubclassingInstantiationStrategy.
0150: * @see CglibSubclassingInstantiationStrategy
0151: */
0152: public void setInstantiationStrategy(
0153: InstantiationStrategy instantiationStrategy) {
0154: this .instantiationStrategy = instantiationStrategy;
0155: }
0156:
0157: /**
0158: * Return the instantiation strategy to use for creating bean instances.
0159: */
0160: protected InstantiationStrategy getInstantiationStrategy() {
0161: return this .instantiationStrategy;
0162: }
0163:
0164: /**
0165: * Set whether to allow circular references between beans - and automatically
0166: * try to resolve them.
0167: * <p>Note that circular reference resolution means that one of the involved beans
0168: * will receive a reference to another bean that is not fully initialized yet.
0169: * This can lead to subtle and not-so-subtle side effects on initialization;
0170: * it does work fine for many scenarios, though.
0171: * <p>Default is "true". Turn this off to throw an exception when encountering
0172: * a circular reference, disallowing them completely.
0173: * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
0174: * between your beans. Refactor your application logic to have the two beans
0175: * involved delegate to a third bean that encapsulates their common logic.
0176: */
0177: public void setAllowCircularReferences(
0178: boolean allowCircularReferences) {
0179: this .allowCircularReferences = allowCircularReferences;
0180: }
0181:
0182: /**
0183: * Set whether to allow the raw injection of a bean instance into some other
0184: * bean's property, despite the injected bean eventually getting wrapped
0185: * (for example, through AOP auto-proxying).
0186: * <p>This will only be used as a last resort in case of a circular reference
0187: * that cannot be resolved otherwise: essentially, preferring a raw instance
0188: * getting injected over a failure of the entire bean wiring process.
0189: * <p>Default is "false", as of Spring 2.0. Turn this on to allow for non-wrapped
0190: * raw beans injected into some of your references, which was Spring 1.2's
0191: * (arguably unclean) default behavior.
0192: * <p><b>NOTE:</b> It is generally recommended to not rely on circular references
0193: * between your beans, in particular with auto-proxying involved.
0194: * @see #setAllowCircularReferences
0195: */
0196: public void setAllowRawInjectionDespiteWrapping(
0197: boolean allowRawInjectionDespiteWrapping) {
0198: this .allowRawInjectionDespiteWrapping = allowRawInjectionDespiteWrapping;
0199: }
0200:
0201: /**
0202: * Ignore the given dependency type for autowiring:
0203: * for example, String. Default is none.
0204: */
0205: public void ignoreDependencyType(Class type) {
0206: this .ignoredDependencyTypes.add(type);
0207: }
0208:
0209: /**
0210: * Ignore the given dependency interface for autowiring.
0211: * <p>This will typically be used by application contexts to register
0212: * dependencies that are resolved in other ways, like BeanFactory through
0213: * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
0214: * <p>By default, only the BeanFactoryAware interface is ignored.
0215: * For further types to ignore, invoke this method for each type.
0216: * @see org.springframework.beans.factory.BeanFactoryAware
0217: * @see org.springframework.context.ApplicationContextAware
0218: */
0219: public void ignoreDependencyInterface(Class ifc) {
0220: this .ignoredDependencyInterfaces.add(ifc);
0221: }
0222:
0223: public void copyConfigurationFrom(
0224: ConfigurableBeanFactory otherFactory) {
0225: super .copyConfigurationFrom(otherFactory);
0226: if (otherFactory instanceof AbstractAutowireCapableBeanFactory) {
0227: AbstractAutowireCapableBeanFactory otherAutowireFactory = (AbstractAutowireCapableBeanFactory) otherFactory;
0228: this .instantiationStrategy = otherAutowireFactory.instantiationStrategy;
0229: this .allowCircularReferences = otherAutowireFactory.allowCircularReferences;
0230: this .ignoredDependencyTypes
0231: .addAll(otherAutowireFactory.ignoredDependencyTypes);
0232: this .ignoredDependencyInterfaces
0233: .addAll(otherAutowireFactory.ignoredDependencyInterfaces);
0234: }
0235: }
0236:
0237: //---------------------------------------------------------------------
0238: // Implementation of AutowireCapableBeanFactory interface
0239: //---------------------------------------------------------------------
0240:
0241: public Object createBean(Class beanClass, int autowireMode,
0242: boolean dependencyCheck) throws BeansException {
0243:
0244: // Use non-singleton bean definition, to avoid registering bean as dependent bean.
0245: RootBeanDefinition bd = new RootBeanDefinition(beanClass,
0246: autowireMode, dependencyCheck);
0247: bd.setSingleton(false);
0248: return createBean(beanClass.getName(), bd, null);
0249: }
0250:
0251: public Object autowire(Class beanClass, int autowireMode,
0252: boolean dependencyCheck) throws BeansException {
0253:
0254: // Use non-singleton bean definition, to avoid registering bean as dependent bean.
0255: RootBeanDefinition bd = new RootBeanDefinition(beanClass,
0256: autowireMode, dependencyCheck);
0257: bd.setSingleton(false);
0258: if (bd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR) {
0259: return autowireConstructor(beanClass.getName(), bd, null)
0260: .getWrappedInstance();
0261: } else {
0262: Object bean = getInstantiationStrategy().instantiate(bd,
0263: null, this );
0264: populateBean(beanClass.getName(), bd, new BeanWrapperImpl(
0265: bean));
0266: return bean;
0267: }
0268: }
0269:
0270: public void autowireBeanProperties(Object existingBean,
0271: int autowireMode, boolean dependencyCheck)
0272: throws BeansException {
0273:
0274: if (autowireMode != AUTOWIRE_BY_NAME
0275: && autowireMode != AUTOWIRE_BY_TYPE) {
0276: throw new IllegalArgumentException(
0277: "Just constants AUTOWIRE_BY_NAME and AUTOWIRE_BY_TYPE allowed");
0278: }
0279: // Use non-singleton bean definition, to avoid registering bean as dependent bean.
0280: RootBeanDefinition bd = new RootBeanDefinition(existingBean
0281: .getClass(), autowireMode, dependencyCheck);
0282: bd.setSingleton(false);
0283: populateBean(existingBean.getClass().getName(), bd,
0284: new BeanWrapperImpl(existingBean));
0285: }
0286:
0287: public void applyBeanPropertyValues(Object existingBean,
0288: String beanName) throws BeansException {
0289: RootBeanDefinition bd = getMergedBeanDefinition(beanName, true);
0290: BeanWrapper bw = new BeanWrapperImpl(existingBean);
0291: initBeanWrapper(bw);
0292: applyPropertyValues(beanName, bd, bw, bd.getPropertyValues());
0293: }
0294:
0295: public Object configureBean(Object existingBean, String beanName)
0296: throws BeansException {
0297: RootBeanDefinition bd = getMergedBeanDefinition(beanName, true);
0298: BeanWrapper bw = new BeanWrapperImpl(existingBean);
0299: initBeanWrapper(bw);
0300: populateBean(beanName, bd, bw);
0301: return initializeBean(beanName, existingBean, bd);
0302: }
0303:
0304: public Object initializeBean(Object existingBean, String beanName) {
0305: return initializeBean(beanName, existingBean, null);
0306: }
0307:
0308: public Object applyBeanPostProcessorsBeforeInitialization(
0309: Object existingBean, String beanName) throws BeansException {
0310:
0311: Object result = existingBean;
0312: for (Iterator it = getBeanPostProcessors().iterator(); it
0313: .hasNext();) {
0314: BeanPostProcessor beanProcessor = (BeanPostProcessor) it
0315: .next();
0316: result = beanProcessor.postProcessBeforeInitialization(
0317: result, beanName);
0318: }
0319: return result;
0320: }
0321:
0322: public Object applyBeanPostProcessorsAfterInitialization(
0323: Object existingBean, String beanName) throws BeansException {
0324:
0325: Object result = existingBean;
0326: for (Iterator it = getBeanPostProcessors().iterator(); it
0327: .hasNext();) {
0328: BeanPostProcessor beanProcessor = (BeanPostProcessor) it
0329: .next();
0330: result = beanProcessor.postProcessAfterInitialization(
0331: result, beanName);
0332: }
0333: return result;
0334: }
0335:
0336: //---------------------------------------------------------------------
0337: // Implementation of relevant AbstractBeanFactory template methods
0338: //---------------------------------------------------------------------
0339:
0340: /**
0341: * Central method of this class: creates a bean instance,
0342: * populates the bean instance, applies post-processors, etc.
0343: * <p>Differentiates between default bean instantiation, use of a
0344: * factory method, and autowiring a constructor.
0345: * @see #instantiateBean
0346: * @see #instantiateUsingFactoryMethod
0347: * @see #autowireConstructor
0348: */
0349: protected Object createBean(String beanName,
0350: RootBeanDefinition mbd, Object[] args)
0351: throws BeanCreationException {
0352:
0353: // Guarantee initialization of beans that the current one depends on.
0354: if (mbd.getDependsOn() != null) {
0355: for (int i = 0; i < mbd.getDependsOn().length; i++) {
0356: getBean(mbd.getDependsOn()[i]);
0357: }
0358: }
0359:
0360: if (logger.isDebugEnabled()) {
0361: logger.debug("Creating instance of bean '" + beanName
0362: + "' with merged definition [" + mbd + "]");
0363: }
0364:
0365: // Make sure bean class is actually resolved at this point.
0366: Class beanClass = resolveBeanClass(mbd, beanName);
0367:
0368: // Prepare method overrides.
0369: try {
0370: mbd.prepareMethodOverrides();
0371: } catch (BeanDefinitionValidationException ex) {
0372: throw new BeanDefinitionStoreException(mbd
0373: .getResourceDescription(), beanName,
0374: "Validation of method overrides failed", ex);
0375: }
0376:
0377: String errorMessage = null;
0378:
0379: try {
0380: // Instantiate the bean.
0381: errorMessage = "BeanPostProcessor before instantiation of bean failed";
0382:
0383: // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
0384: if (beanClass != null && !mbd.isSynthetic()
0385: && hasInstantiationAwareBeanPostProcessors()) {
0386: Object bean = applyBeanPostProcessorsBeforeInstantiation(
0387: beanClass, beanName);
0388: if (bean != null) {
0389: bean = applyBeanPostProcessorsAfterInitialization(
0390: bean, beanName);
0391: return bean;
0392: }
0393: }
0394:
0395: // Instantiate the bean.
0396: errorMessage = "Instantiation of bean failed";
0397:
0398: BeanWrapper instanceWrapper = null;
0399: if (mbd.isSingleton()) {
0400: synchronized (getSingletonMutex()) {
0401: instanceWrapper = (BeanWrapper) this .factoryBeanInstanceCache
0402: .remove(beanName);
0403: }
0404: }
0405:
0406: if (instanceWrapper == null) {
0407: instanceWrapper = createBeanInstance(beanName, mbd,
0408: args);
0409: }
0410: Object bean = (instanceWrapper != null ? instanceWrapper
0411: .getWrappedInstance() : null);
0412:
0413: // Eagerly cache singletons to be able to resolve circular references
0414: // even when triggered by lifecycle interfaces like BeanFactoryAware.
0415: if (mbd.isSingleton() && this .allowCircularReferences
0416: && isSingletonCurrentlyInCreation(beanName)) {
0417: if (logger.isDebugEnabled()) {
0418: logger
0419: .debug("Eagerly caching bean '"
0420: + beanName
0421: + "' to allow for resolving potential circular references");
0422: }
0423: addSingleton(beanName, bean);
0424: }
0425:
0426: // Initialize the bean instance.
0427: errorMessage = "Initialization of bean failed";
0428:
0429: // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
0430: // state of the bean before properties are set. This can be used, for example,
0431: // to support styles of field injection.
0432: boolean continueWithPropertyPopulation = true;
0433:
0434: if (!mbd.isSynthetic()
0435: && hasInstantiationAwareBeanPostProcessors()) {
0436: for (Iterator it = getBeanPostProcessors().iterator(); it
0437: .hasNext();) {
0438: BeanPostProcessor beanProcessor = (BeanPostProcessor) it
0439: .next();
0440: if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
0441: InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
0442: if (!ibp.postProcessAfterInstantiation(bean,
0443: beanName)) {
0444: continueWithPropertyPopulation = false;
0445: break;
0446: }
0447: }
0448: }
0449: }
0450:
0451: if (continueWithPropertyPopulation) {
0452: populateBean(beanName, mbd, instanceWrapper);
0453: }
0454:
0455: Object originalBean = bean;
0456: bean = initializeBean(beanName, bean, mbd);
0457:
0458: if (!this .allowRawInjectionDespiteWrapping
0459: && originalBean != bean && mbd.isSingleton()
0460: && hasDependentBean(beanName)) {
0461: throw new BeanCurrentlyInCreationException(
0462: beanName,
0463: "Bean with name '"
0464: + beanName
0465: + "' has been injected into other beans "
0466: + getDependentBeans(beanName)
0467: + " in its raw version as part of a circular reference, "
0468: + "but has eventually been wrapped (for example as part of auto-proxy creation). "
0469: + "This means that said other beans do not use the final version of the bean. "
0470: + "This is often the result of over-eager type matching - consider using "
0471: + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
0472: }
0473:
0474: // Register bean as disposable, and also as dependent on specified "dependsOn" beans.
0475: registerDisposableBeanIfNecessary(beanName, originalBean,
0476: mbd);
0477:
0478: return bean;
0479: }
0480:
0481: catch (BeanCreationException ex) {
0482: throw ex;
0483: } catch (Throwable ex) {
0484: throw new BeanCreationException(mbd
0485: .getResourceDescription(), beanName, errorMessage,
0486: ex);
0487: }
0488: }
0489:
0490: /**
0491: * Predict the eventual bean type for the given bean.
0492: * @param beanName the name of the bean
0493: * @param mbd the merged bean definition to determine the type for
0494: * @return the type of the bean, or <code>null</code> if not predictable
0495: */
0496: protected Class predictBeanType(String beanName,
0497: RootBeanDefinition mbd) {
0498: Class beanClass = null;
0499: if (mbd.getFactoryMethodName() != null) {
0500: beanClass = getTypeForFactoryMethod(beanName, mbd);
0501: } else {
0502: beanClass = resolveBeanClass(mbd, beanName);
0503: }
0504: // Apply SmartInstantiationAwareBeanPostProcessors to predict the
0505: // eventual type after a before-instantiation shortcut.
0506: if (!mbd.isSynthetic()
0507: && hasInstantiationAwareBeanPostProcessors()) {
0508: for (Iterator it = getBeanPostProcessors().iterator(); it
0509: .hasNext();) {
0510: BeanPostProcessor bp = (BeanPostProcessor) it.next();
0511: if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
0512: SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
0513: Class processedType = ibp.predictBeanType(
0514: beanClass, beanName);
0515: if (processedType != null) {
0516: return processedType;
0517: }
0518: }
0519: }
0520: }
0521: return beanClass;
0522: }
0523:
0524: /**
0525: * Determine the bean type for the given bean definition which is based on
0526: * a factory method. Only called if there is no singleton instance registered
0527: * for the target bean already.
0528: * <p>This implementation determines the type matching {@link #createBean}'s
0529: * different creation strategies. As far as possible, we'll perform static
0530: * type checking to avoid creation of the target bean.
0531: * @param beanName the name of the bean (for error handling purposes)
0532: * @param mbd the merged bean definition for the bean
0533: * @return the type for the bean if determinable, or <code>null</code> else
0534: * @see #createBean
0535: */
0536: protected Class getTypeForFactoryMethod(String beanName,
0537: RootBeanDefinition mbd) {
0538: Class factoryClass = null;
0539: boolean isStatic = true;
0540:
0541: if (mbd.getFactoryBeanName() != null) {
0542: // Check declared factory method return type on factory class.
0543: factoryClass = getType(mbd.getFactoryBeanName());
0544: isStatic = false;
0545: } else {
0546: // Check declared factory method return type on bean class.
0547: factoryClass = resolveBeanClass(mbd, beanName);
0548: }
0549:
0550: if (factoryClass == null) {
0551: return null;
0552: }
0553:
0554: // If all factory methods have the same return type, return that type.
0555: // Can't clearly figure out exact method due to type converting / autowiring!
0556: int minNrOfArgs = mbd.getConstructorArgumentValues()
0557: .getArgumentCount();
0558: Method[] candidates = ReflectionUtils
0559: .getAllDeclaredMethods(factoryClass);
0560: Set returnTypes = new HashSet(1);
0561: for (int i = 0; i < candidates.length; i++) {
0562: Method factoryMethod = candidates[i];
0563: if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic
0564: && factoryMethod.getName().equals(
0565: mbd.getFactoryMethodName())
0566: && factoryMethod.getParameterTypes().length >= minNrOfArgs) {
0567: returnTypes.add(factoryMethod.getReturnType());
0568: }
0569: }
0570:
0571: if (returnTypes.size() == 1) {
0572: // Clear return type found: all factory methods return same type.
0573: return (Class) returnTypes.iterator().next();
0574: } else {
0575: // Ambiguous return types found: return null to indicate "not determinable".
0576: return null;
0577: }
0578: }
0579:
0580: /**
0581: * This implementation checks the FactoryBean's <code>getObjectType</code> method
0582: * on a plain instance of the FactoryBean, without bean properties applied yet.
0583: * If this doesn't return a type yet, a full creation of the FactoryBean is
0584: * used as fallback (through delegation to the superclass's implementation).
0585: * <p>The shortcut check for a FactoryBean is only applied in case of a singleton
0586: * FactoryBean. If the FactoryBean instance itself is not kept as singleton,
0587: * it will be fully created to check the type of its exposed object.
0588: */
0589: protected Class getTypeForFactoryBean(String beanName,
0590: RootBeanDefinition mbd) {
0591: FactoryBean fb = (mbd.isSingleton() ? getSingletonFactoryBeanForTypeCheck(
0592: beanName, mbd)
0593: : getNonSingletonFactoryBeanForTypeCheck(beanName, mbd));
0594:
0595: if (fb != null) {
0596: // Try to obtain the FactoryBean's object type from this early stage of the instance.
0597: try {
0598: Class type = fb.getObjectType();
0599: if (type != null) {
0600: return type;
0601: }
0602: } catch (Throwable ex) {
0603: // Thrown from the FactoryBean's getObjectType implementation.
0604: logger
0605: .warn(
0606: "FactoryBean threw exception from getObjectType, despite the contract saying "
0607: + "that it should return null if the type of its object cannot be determined yet",
0608: ex);
0609: }
0610: }
0611:
0612: // No type found - fall back to full creation of the FactoryBean instance.
0613: return super .getTypeForFactoryBean(beanName, mbd);
0614: }
0615:
0616: //---------------------------------------------------------------------
0617: // Implementation methods
0618: //---------------------------------------------------------------------
0619:
0620: /**
0621: * Obtain a "shortcut" singleton FactoryBean instance to use for a
0622: * <code>getObjectType()</code> call, without full initialization
0623: * of the FactoryBean.
0624: * @param beanName the name of the bean
0625: * @param mbd the bean definition for the bean
0626: * @return the FactoryBean instance, or <code>null</code> to indicate
0627: * that we couldn't obtain a shortcut FactoryBean instance
0628: */
0629: private FactoryBean getSingletonFactoryBeanForTypeCheck(
0630: String beanName, RootBeanDefinition mbd) {
0631: synchronized (getSingletonMutex()) {
0632: BeanWrapper bw = (BeanWrapper) this .factoryBeanInstanceCache
0633: .get(beanName);
0634: if (bw != null) {
0635: return (FactoryBean) bw.getWrappedInstance();
0636: }
0637: if (isSingletonCurrentlyInCreation(beanName)) {
0638: return null;
0639: }
0640: Object instance = null;
0641: try {
0642: // Mark this bean as currently in creation, even if just partially.
0643: beforeSingletonCreation(beanName);
0644: // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
0645: Class beanClass = resolveBeanClass(mbd, beanName);
0646: if (beanClass != null && !mbd.isSynthetic()
0647: && hasInstantiationAwareBeanPostProcessors()) {
0648: Object bean = applyBeanPostProcessorsBeforeInstantiation(
0649: beanClass, beanName);
0650: if (bean != null) {
0651: instance = applyBeanPostProcessorsAfterInitialization(
0652: bean, beanName);
0653: }
0654: }
0655: if (instance == null) {
0656: bw = createBeanInstance(beanName, mbd, null);
0657: instance = bw.getWrappedInstance();
0658: }
0659: } finally {
0660: // Finished partial creation of this bean.
0661: afterSingletonCreation(beanName);
0662: }
0663: if (!(instance instanceof FactoryBean)) {
0664: throw new BeanCreationException(beanName,
0665: "Bean instance of type [" + instance.getClass()
0666: + "] is not a FactoryBean");
0667: }
0668: if (bw != null) {
0669: this .factoryBeanInstanceCache.put(beanName, bw);
0670: }
0671: return (FactoryBean) instance;
0672: }
0673: }
0674:
0675: /**
0676: * Obtain a "shortcut" non-singleton FactoryBean instance to use for a
0677: * <code>getObjectType()</code> call, without full initialization
0678: * of the FactoryBean.
0679: * @param beanName the name of the bean
0680: * @param mbd the bean definition for the bean
0681: * @return the FactoryBean instance, or <code>null</code> to indicate
0682: * that we couldn't obtain a shortcut FactoryBean instance
0683: */
0684: private FactoryBean getNonSingletonFactoryBeanForTypeCheck(
0685: String beanName, RootBeanDefinition mbd) {
0686: if (isPrototypeCurrentlyInCreation(beanName)) {
0687: return null;
0688: }
0689: Object instance = null;
0690: try {
0691: // Mark this bean as currently in creation, even if just partially.
0692: beforePrototypeCreation(beanName);
0693: // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
0694: Class beanClass = resolveBeanClass(mbd, beanName);
0695: if (beanClass != null && !mbd.isSynthetic()
0696: && hasInstantiationAwareBeanPostProcessors()) {
0697: Object bean = applyBeanPostProcessorsBeforeInstantiation(
0698: beanClass, beanName);
0699: if (bean != null) {
0700: instance = applyBeanPostProcessorsAfterInitialization(
0701: bean, beanName);
0702: }
0703: }
0704: if (instance == null) {
0705: BeanWrapper bw = createBeanInstance(beanName, mbd, null);
0706: instance = bw.getWrappedInstance();
0707: }
0708: } finally {
0709: // Finished partial creation of this bean.
0710: afterPrototypeCreation(beanName);
0711: }
0712: if (!(instance instanceof FactoryBean)) {
0713: throw new BeanCreationException(beanName,
0714: "Bean instance of type [" + instance.getClass()
0715: + "] is not a FactoryBean");
0716: }
0717: return (FactoryBean) instance;
0718: }
0719:
0720: /**
0721: * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
0722: * (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods.
0723: * <p>Any returned object will be used as the bean instead of actually instantiating
0724: * the target bean. A <code>null</code> return value from the post-processor will
0725: * result in the target bean being instantiated.
0726: * @param beanClass the class of the bean to be instantiated
0727: * @param beanName the name of the bean
0728: * @return the bean object to use instead of a default instance of the target bean, or <code>null</code>
0729: * @throws BeansException if any post-processing failed
0730: * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
0731: */
0732: protected Object applyBeanPostProcessorsBeforeInstantiation(
0733: Class beanClass, String beanName) throws BeansException {
0734:
0735: for (Iterator it = getBeanPostProcessors().iterator(); it
0736: .hasNext();) {
0737: BeanPostProcessor beanProcessor = (BeanPostProcessor) it
0738: .next();
0739: if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
0740: InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
0741: Object result = ibp.postProcessBeforeInstantiation(
0742: beanClass, beanName);
0743: if (result != null) {
0744: return result;
0745: }
0746: }
0747: }
0748: return null;
0749: }
0750:
0751: /**
0752: * Create a new instance for the specified bean, using an appropriate instantiation strategy:
0753: * factory method, constructor autowiring, or simple instantiation.
0754: * @param beanName the name of the bean
0755: * @param mbd the bean definition for the bean
0756: * @param args arguments to use if creating a prototype using explicit arguments to a
0757: * static factory method. It is invalid to use a non-null args value in any other case.
0758: * @return BeanWrapper for the new instance
0759: * @see #instantiateUsingFactoryMethod
0760: * @see #autowireConstructor
0761: * @see #instantiateBean
0762: */
0763: protected BeanWrapper createBeanInstance(String beanName,
0764: RootBeanDefinition mbd, Object[] args) {
0765: if (mbd.getFactoryMethodName() != null) {
0766: return instantiateUsingFactoryMethod(beanName, mbd, args);
0767: }
0768:
0769: // Need to determine the constructor...
0770: Constructor constructor = determineConstructorFromBeanPostProcessors(
0771: mbd.getBeanClass(), beanName);
0772: if (constructor != null
0773: || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR
0774: || mbd.hasConstructorArgumentValues()) {
0775: return autowireConstructor(beanName, mbd, constructor);
0776: }
0777:
0778: // No special handling: simply use no-arg constructor.
0779: return instantiateBean(beanName, mbd);
0780: }
0781:
0782: /**
0783: * Determine the constructor to use for the given bean, checking all registered
0784: * {@link SmartInstantiationAwareBeanPostProcessor SmartInstantiationAwareBeanPostProcessors}.
0785: * @param beanClass the raw class of the bean
0786: * @param beanName the name of the bean
0787: * @return the constructor to use, or <code>null</code> if none specified
0788: * @throws org.springframework.beans.BeansException in case of errors
0789: * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineConstructor
0790: */
0791: protected Constructor determineConstructorFromBeanPostProcessors(
0792: Class beanClass, String beanName) throws BeansException {
0793:
0794: for (Iterator it = getBeanPostProcessors().iterator(); it
0795: .hasNext();) {
0796: BeanPostProcessor beanProcessor = (BeanPostProcessor) it
0797: .next();
0798: if (beanProcessor instanceof SmartInstantiationAwareBeanPostProcessor) {
0799: SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) beanProcessor;
0800: Constructor ctor = ibp.determineConstructor(beanClass,
0801: beanName);
0802: if (ctor != null) {
0803: return ctor;
0804: }
0805: }
0806: }
0807: return null;
0808: }
0809:
0810: /**
0811: * Instantiate the given bean using its default constructor.
0812: * @param beanName the name of the bean
0813: * @param mbd the bean definition for the bean
0814: * @return BeanWrapper for the new instance
0815: */
0816: protected BeanWrapper instantiateBean(String beanName,
0817: RootBeanDefinition mbd) {
0818: Object beanInstance = getInstantiationStrategy().instantiate(
0819: mbd, beanName, this );
0820: BeanWrapper bw = new BeanWrapperImpl(beanInstance);
0821: initBeanWrapper(bw);
0822: return bw;
0823: }
0824:
0825: /**
0826: * Instantiate the bean using a named factory method. The method may be static, if the
0827: * mbd parameter specifies a class, rather than a factoryBean, or
0828: * an instance variable on a factory object itself configured using Dependency Injection.
0829: * <p>Implementation requires iterating over the static or instance methods with the
0830: * name specified in the RootBeanDefinition (the method may be overloaded) and trying
0831: * to match with the parameters. We don't have the types attached to constructor args,
0832: * so trial and error is the only way to go here. The explicitArgs array may contain
0833: * argument values passed in programmatically via the corresponding getBean method.
0834: * @param beanName the name of the bean
0835: * @param mbd the bean definition for the bean
0836: * @param explicitArgs argument values passed in programmatically via the getBean
0837: * method, or <code>null</code> if none (-> use constructor argument values from bean definition)
0838: * @return BeanWrapper for the new instance
0839: * @see #getBean(String, Object[])
0840: */
0841: protected BeanWrapper instantiateUsingFactoryMethod(
0842: String beanName, RootBeanDefinition mbd,
0843: Object[] explicitArgs) {
0844:
0845: ConstructorResolver constructorResolver = new ConstructorResolverAdapter();
0846: return constructorResolver.instantiateUsingFactoryMethod(
0847: beanName, mbd, explicitArgs);
0848: }
0849:
0850: /**
0851: * "autowire constructor" (with constructor arguments by type) behavior.
0852: * Also applied if explicit constructor argument values are specified,
0853: * matching all remaining arguments with beans from the bean factory.
0854: * <p>This corresponds to constructor injection: In this mode, a Spring
0855: * bean factory is able to host components that expect constructor-based
0856: * dependency resolution.
0857: * @param beanName the name of the bean
0858: * @param mbd the bean definition for the bean
0859: * @param ctor the chosen candidate constructor
0860: * @return BeanWrapper for the new instance
0861: */
0862: protected BeanWrapper autowireConstructor(String beanName,
0863: RootBeanDefinition mbd, Constructor ctor) {
0864: ConstructorResolver constructorResolver = new ConstructorResolverAdapter();
0865: return constructorResolver.autowireConstructor(beanName, mbd,
0866: ctor);
0867: }
0868:
0869: /**
0870: * Populate the bean instance in the given BeanWrapper with the property values
0871: * from the bean definition.
0872: * @param beanName the name of the bean
0873: * @param mbd the bean definition for the bean
0874: * @param bw BeanWrapper with bean instance
0875: */
0876: protected void populateBean(String beanName,
0877: RootBeanDefinition mbd, BeanWrapper bw) {
0878: PropertyValues pvs = mbd.getPropertyValues();
0879:
0880: if (bw == null) {
0881: if (!pvs.isEmpty()) {
0882: throw new BeanCreationException(beanName,
0883: "Cannot apply property values to null instance");
0884: } else {
0885: // Skip property population phase for null instance.
0886: return;
0887: }
0888: }
0889:
0890: if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME
0891: || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
0892: MutablePropertyValues newPvs = new MutablePropertyValues(
0893: pvs);
0894:
0895: // Add property values based on autowire by name if applicable.
0896: if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
0897: autowireByName(beanName, mbd, bw, newPvs);
0898: }
0899:
0900: // Add property values based on autowire by type if applicable.
0901: if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
0902: autowireByType(beanName, mbd, bw, newPvs);
0903: }
0904:
0905: pvs = newPvs;
0906: }
0907:
0908: boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
0909: boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
0910:
0911: if (hasInstAwareBpps || needsDepCheck) {
0912: PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);
0913: if (hasInstAwareBpps) {
0914: for (Iterator it = getBeanPostProcessors().iterator(); it
0915: .hasNext();) {
0916: BeanPostProcessor beanProcessor = (BeanPostProcessor) it
0917: .next();
0918: if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
0919: InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
0920: pvs = ibp.postProcessPropertyValues(pvs,
0921: filteredPds, bw.getWrappedInstance(),
0922: beanName);
0923: if (pvs == null) {
0924: return;
0925: }
0926: }
0927: }
0928: }
0929: if (needsDepCheck) {
0930: checkDependencies(beanName, mbd, filteredPds, pvs);
0931: }
0932: }
0933:
0934: applyPropertyValues(beanName, mbd, bw, pvs);
0935: }
0936:
0937: /**
0938: * Fill in any missing property values with references to
0939: * other beans in this factory if autowire is set to "byName".
0940: * @param beanName the name of the bean we're wiring up.
0941: * Useful for debugging messages; not used functionally.
0942: * @param mbd bean definition to update through autowiring
0943: * @param bw BeanWrapper from which we can obtain information about the bean
0944: * @param pvs the PropertyValues to register wired objects with
0945: */
0946: protected void autowireByName(String beanName,
0947: RootBeanDefinition mbd, BeanWrapper bw,
0948: MutablePropertyValues pvs) {
0949:
0950: String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
0951: for (int i = 0; i < propertyNames.length; i++) {
0952: String propertyName = propertyNames[i];
0953: if (containsBean(propertyName)) {
0954: Object bean = getBean(propertyName);
0955: pvs.addPropertyValue(propertyName, bean);
0956: if (mbd.isSingleton()) {
0957: registerDependentBean(propertyName, beanName);
0958: }
0959: if (logger.isDebugEnabled()) {
0960: logger
0961: .debug("Added autowiring by name from bean name '"
0962: + beanName
0963: + "' via property '"
0964: + propertyName
0965: + "' to bean named '"
0966: + propertyName + "'");
0967: }
0968: } else {
0969: if (logger.isTraceEnabled()) {
0970: logger.trace("Not autowiring property '"
0971: + propertyName + "' of bean '" + beanName
0972: + "' by name: no matching bean found");
0973: }
0974: }
0975: }
0976: }
0977:
0978: /**
0979: * Abstract method defining "autowire by type" (bean properties by type) behavior.
0980: * <p>This is like PicoContainer default, in which there must be exactly one bean
0981: * of the property type in the bean factory. This makes bean factories simple to
0982: * configure for small namespaces, but doesn't work as well as standard Spring
0983: * behavior for bigger applications.
0984: * @param beanName the name of the bean to autowire by type
0985: * @param mbd the merged bean definition to update through autowiring
0986: * @param bw BeanWrapper from which we can obtain information about the bean
0987: * @param pvs the PropertyValues to register wired objects with
0988: */
0989: protected void autowireByType(String beanName,
0990: RootBeanDefinition mbd, BeanWrapper bw,
0991: MutablePropertyValues pvs) {
0992:
0993: String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
0994: for (int i = 0; i < propertyNames.length; i++) {
0995: String propertyName = propertyNames[i];
0996: // look for a matching type
0997: Class requiredType = bw.getPropertyDescriptor(propertyName)
0998: .getPropertyType();
0999: Map matchingBeans = findAutowireCandidates(beanName,
1000: requiredType);
1001: // Let's see how many matching beans we got...
1002: int count = matchingBeans.size();
1003: if (count == 1) {
1004: Map.Entry entry = (Map.Entry) matchingBeans.entrySet()
1005: .iterator().next();
1006: String autowiredBeanName = (String) entry.getKey();
1007: Object autowiredBean = entry.getValue();
1008: pvs.addPropertyValue(propertyName, autowiredBean);
1009: if (mbd.isSingleton()) {
1010: registerDependentBean(autowiredBeanName, beanName);
1011: }
1012: if (logger.isDebugEnabled()) {
1013: logger.debug("Autowiring by type from bean name '"
1014: + beanName + "' via property '"
1015: + propertyName + "' to bean named '"
1016: + autowiredBeanName + "'");
1017: }
1018: } else if (count > 1) {
1019: throw new UnsatisfiedDependencyException(
1020: mbd.getResourceDescription(),
1021: beanName,
1022: propertyName,
1023: "There are "
1024: + matchingBeans.size()
1025: + " beans of type ["
1026: + requiredType.getName()
1027: + "] available for autowiring by type: "
1028: + matchingBeans.keySet()
1029: + ". There should have been exactly 1 to be able to autowire property '"
1030: + propertyName
1031: + "' of bean '"
1032: + beanName
1033: + "'. Consider using autowiring by name instead.");
1034: } else {
1035: if (logger.isTraceEnabled()) {
1036: logger.trace("Not autowiring property '"
1037: + propertyName + "' of bean '" + beanName
1038: + "' by type: no matching bean found");
1039: }
1040: }
1041: }
1042: }
1043:
1044: /**
1045: * Return an array of non-simple bean properties that are unsatisfied.
1046: * These are probably unsatisfied references to other beans in the
1047: * factory. Does not include simple properties like primitives or Strings.
1048: * @param mbd the merged bean definition the bean was created with
1049: * @param bw the BeanWrapper the bean was created with
1050: * @return an array of bean property names
1051: * @see org.springframework.beans.BeanUtils#isSimpleProperty
1052: */
1053: protected String[] unsatisfiedNonSimpleProperties(
1054: RootBeanDefinition mbd, BeanWrapper bw) {
1055: Set result = new TreeSet();
1056: PropertyValues pvs = mbd.getPropertyValues();
1057: PropertyDescriptor[] pds = bw.getPropertyDescriptors();
1058: for (int i = 0; i < pds.length; i++) {
1059: if (pds[i].getWriteMethod() != null
1060: && !isExcludedFromDependencyCheck(pds[i])
1061: && !pvs.contains(pds[i].getName())
1062: && !BeanUtils.isSimpleProperty(pds[i]
1063: .getPropertyType())) {
1064: result.add(pds[i].getName());
1065: }
1066: }
1067: return StringUtils.toStringArray(result);
1068: }
1069:
1070: /**
1071: * Extract a filtered set of PropertyDescriptors from the given BeanWrapper,
1072: * excluding ignored dependency types or properties defined on ignored
1073: * dependency interfaces.
1074: * @param bw the BeanWrapper the bean was created with
1075: * @return the filtered PropertyDescriptors
1076: * @see #isExcludedFromDependencyCheck
1077: */
1078: protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(
1079: BeanWrapper bw) {
1080: synchronized (this .filteredPropertyDescriptorsCache) {
1081: PropertyDescriptor[] filtered = (PropertyDescriptor[]) this .filteredPropertyDescriptorsCache
1082: .get(bw.getWrappedClass());
1083: if (filtered == null) {
1084: List pds = new LinkedList(Arrays.asList(bw
1085: .getPropertyDescriptors()));
1086: for (Iterator it = pds.iterator(); it.hasNext();) {
1087: PropertyDescriptor pd = (PropertyDescriptor) it
1088: .next();
1089: if (isExcludedFromDependencyCheck(pd)) {
1090: it.remove();
1091: }
1092: }
1093: filtered = (PropertyDescriptor[]) pds
1094: .toArray(new PropertyDescriptor[pds.size()]);
1095: this .filteredPropertyDescriptorsCache.put(bw
1096: .getWrappedClass(), filtered);
1097: }
1098: return filtered;
1099: }
1100: }
1101:
1102: /**
1103: * Determine whether the given bean property is excluded from dependency checks.
1104: * <p>This implementation excludes properties defined by CGLIB and
1105: * properties whose type matches an ignored dependency type or which
1106: * are defined by an ignored dependency interface.
1107: * @param pd the PropertyDescriptor of the bean property
1108: * @return whether the bean property is excluded
1109: * @see #ignoreDependencyType(Class)
1110: * @see #ignoreDependencyInterface(Class)
1111: */
1112: protected boolean isExcludedFromDependencyCheck(
1113: PropertyDescriptor pd) {
1114: return (AutowireUtils.isExcludedFromDependencyCheck(pd)
1115: || this .ignoredDependencyTypes.contains(pd
1116: .getPropertyType()) || AutowireUtils
1117: .isSetterDefinedInInterface(pd,
1118: this .ignoredDependencyInterfaces));
1119: }
1120:
1121: /**
1122: * Perform a dependency check that all properties exposed have been set,
1123: * if desired. Dependency checks can be objects (collaborating beans),
1124: * simple (primitives and String), or all (both).
1125: * @param beanName the name of the bean
1126: * @param mbd the merged bean definition the bean was created with
1127: * @param pds the relevant property descriptors for the target bean
1128: * @param pvs the property values to be applied to the bean
1129: * @see #isExcludedFromDependencyCheck(java.beans.PropertyDescriptor)
1130: */
1131: protected void checkDependencies(String beanName,
1132: RootBeanDefinition mbd, PropertyDescriptor[] pds,
1133: PropertyValues pvs) throws UnsatisfiedDependencyException {
1134:
1135: int dependencyCheck = mbd.getDependencyCheck();
1136: for (int i = 0; i < pds.length; i++) {
1137: if (pds[i].getWriteMethod() != null
1138: && !pvs.contains(pds[i].getName())) {
1139: boolean isSimple = BeanUtils.isSimpleProperty(pds[i]
1140: .getPropertyType());
1141: boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL)
1142: || (isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE)
1143: || (!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
1144: if (unsatisfied) {
1145: throw new UnsatisfiedDependencyException(mbd
1146: .getResourceDescription(), beanName, pds[i]
1147: .getName(),
1148: "Set this property value or disable dependency checking for this bean.");
1149: }
1150: }
1151: }
1152: }
1153:
1154: /**
1155: * Apply the given property values, resolving any runtime references
1156: * to other beans in this bean factory. Must use deep copy, so we
1157: * don't permanently modify this property.
1158: * @param beanName the bean name passed for better exception information
1159: * @param mbd the merged bean definition
1160: * @param bw the BeanWrapper wrapping the target object
1161: * @param pvs the new property values
1162: */
1163: protected void applyPropertyValues(String beanName,
1164: RootBeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
1165:
1166: if (pvs == null || pvs.isEmpty()) {
1167: return;
1168: }
1169:
1170: MutablePropertyValues mpvs = null;
1171: List original = null;
1172:
1173: if (pvs instanceof MutablePropertyValues) {
1174: mpvs = (MutablePropertyValues) pvs;
1175: if (mpvs.isConverted()) {
1176: // Shortcut: use the pre-converted values as-is.
1177: try {
1178: bw.setPropertyValues(mpvs);
1179: return;
1180: } catch (BeansException ex) {
1181: throw new BeanCreationException(mbd
1182: .getResourceDescription(), beanName,
1183: "Error setting property values", ex);
1184: }
1185: }
1186: original = mpvs.getPropertyValueList();
1187: } else {
1188: original = Arrays.asList(pvs.getPropertyValues());
1189: }
1190:
1191: BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(
1192: this , beanName, mbd, bw);
1193:
1194: // Create a deep copy, resolving any references for values.
1195: BeanWrapperImpl bwi = (bw instanceof BeanWrapperImpl ? (BeanWrapperImpl) bw
1196: : null);
1197: List deepCopy = new ArrayList(original.size());
1198: boolean resolveNecessary = false;
1199: for (Iterator it = original.iterator(); it.hasNext();) {
1200: PropertyValue pv = (PropertyValue) it.next();
1201: if (pv.isConverted()) {
1202: deepCopy.add(pv);
1203: } else {
1204: String propertyName = pv.getName();
1205: Object originalValue = pv.getValue();
1206: Object resolvedValue = valueResolver
1207: .resolveValueIfNecessary("bean property '"
1208: + propertyName + "'", originalValue);
1209: // Possibly store converted value in merged bean definition,
1210: // in order to avoid re-conversion for every created bean instance.
1211: if (resolvedValue == originalValue) {
1212: if (bwi != null
1213: && !PropertyAccessorUtils
1214: .isNestedOrIndexedProperty(propertyName)) {
1215: pv.setConvertedValue(bwi.convertForProperty(
1216: resolvedValue, propertyName));
1217: }
1218: deepCopy.add(pv);
1219: } else if (originalValue instanceof TypedStringValue
1220: && bwi != null
1221: && !PropertyAccessorUtils
1222: .isNestedOrIndexedProperty(propertyName)) {
1223: pv.setConvertedValue(bwi.convertForProperty(
1224: resolvedValue, propertyName));
1225: deepCopy.add(pv);
1226: } else {
1227: resolveNecessary = true;
1228: deepCopy.add(new PropertyValue(propertyName,
1229: resolvedValue));
1230: }
1231: }
1232: }
1233: if (mpvs != null && !resolveNecessary) {
1234: mpvs.setConverted();
1235: }
1236:
1237: // Set our (possibly massaged) deep copy.
1238: try {
1239: bw.setPropertyValues(new MutablePropertyValues(deepCopy));
1240: } catch (BeansException ex) {
1241: throw new BeanCreationException(mbd
1242: .getResourceDescription(), beanName,
1243: "Error setting property values", ex);
1244: }
1245: }
1246:
1247: /**
1248: * Initialize the given bean instance, applying factory callbacks
1249: * as well as init methods and bean post processors.
1250: * <p>Called from {@link #createBean} for traditionally defined beans,
1251: * and from {@link #initializeBean} for existing bean instances.
1252: * @param beanName the bean name in the factory (for debugging purposes)
1253: * @param bean the new bean instance we may need to initialize
1254: * @param mbd the bean definition that the bean was created with
1255: * (can also be <code>null</code>, if given an existing bean instance)
1256: * @return the initialized bean instance (potentially wrapped)
1257: * @see BeanNameAware
1258: * @see BeanClassLoaderAware
1259: * @see BeanFactoryAware
1260: * @see #applyBeanPostProcessorsBeforeInitialization
1261: * @see #invokeInitMethods
1262: * @see #applyBeanPostProcessorsAfterInitialization
1263: */
1264: protected Object initializeBean(String beanName, Object bean,
1265: RootBeanDefinition mbd) {
1266: if (bean instanceof BeanNameAware) {
1267: ((BeanNameAware) bean).setBeanName(beanName);
1268: }
1269:
1270: if (bean instanceof BeanClassLoaderAware) {
1271: ((BeanClassLoaderAware) bean)
1272: .setBeanClassLoader(getBeanClassLoader());
1273: }
1274:
1275: if (bean instanceof BeanFactoryAware) {
1276: ((BeanFactoryAware) bean).setBeanFactory(this );
1277: }
1278:
1279: Object wrappedBean = bean;
1280: if (mbd == null || !mbd.isSynthetic()) {
1281: wrappedBean = applyBeanPostProcessorsBeforeInitialization(
1282: wrappedBean, beanName);
1283: }
1284:
1285: try {
1286: invokeInitMethods(beanName, wrappedBean, mbd);
1287: } catch (Throwable ex) {
1288: throw new BeanCreationException((mbd != null ? mbd
1289: .getResourceDescription() : null), beanName,
1290: "Invocation of init method failed", ex);
1291: }
1292:
1293: if (mbd == null || !mbd.isSynthetic()) {
1294: wrappedBean = applyBeanPostProcessorsAfterInitialization(
1295: wrappedBean, beanName);
1296: }
1297: return wrappedBean;
1298: }
1299:
1300: /**
1301: * Give a bean a chance to react now all its properties are set,
1302: * and a chance to know about its owning bean factory (this object).
1303: * This means checking whether the bean implements InitializingBean or defines
1304: * a custom init method, and invoking the necessary callback(s) if it does.
1305: * @param beanName the bean name in the factory (for debugging purposes)
1306: * @param bean the new bean instance we may need to initialize
1307: * @param mbd the merged bean definition that the bean was created with
1308: * (can also be <code>null</code>, if given an existing bean instance)
1309: * @throws Throwable if thrown by init methods or by the invocation process
1310: * @see #invokeCustomInitMethod
1311: */
1312: protected void invokeInitMethods(String beanName, Object bean,
1313: RootBeanDefinition mbd) throws Throwable {
1314:
1315: if (bean instanceof InitializingBean) {
1316: ((InitializingBean) bean).afterPropertiesSet();
1317: }
1318:
1319: if (mbd != null && mbd.getInitMethodName() != null) {
1320: invokeCustomInitMethod(beanName, bean, mbd
1321: .getInitMethodName(), mbd.isEnforceInitMethod());
1322: }
1323: }
1324:
1325: /**
1326: * Invoke the specified custom init method on the given bean.
1327: * Called by invokeInitMethods.
1328: * <p>Can be overridden in subclasses for custom resolution of init
1329: * methods with arguments.
1330: * @param beanName the bean name in the factory (for debugging purposes)
1331: * @param bean the new bean instance we may need to initialize
1332: * @param initMethodName the name of the custom init method
1333: * @param enforceInitMethod indicates whether the defined init method needs to exist
1334: * @see #invokeInitMethods
1335: */
1336: protected void invokeCustomInitMethod(String beanName, Object bean,
1337: String initMethodName, boolean enforceInitMethod)
1338: throws Throwable {
1339:
1340: Method initMethod = BeanUtils.findMethod(bean.getClass(),
1341: initMethodName, null);
1342: if (initMethod == null) {
1343: if (enforceInitMethod) {
1344: throw new NoSuchMethodException(
1345: "Couldn't find an init method named '"
1346: + initMethodName
1347: + "' on bean with name '" + beanName
1348: + "'");
1349: } else {
1350: // Ignore non-existent default lifecycle methods.
1351: return;
1352: }
1353: }
1354: if (!Modifier.isPublic(initMethod.getModifiers())
1355: || !Modifier.isPublic(initMethod.getDeclaringClass()
1356: .getModifiers())) {
1357: initMethod.setAccessible(true);
1358: }
1359: try {
1360: initMethod.invoke(bean, (Object[]) null);
1361: } catch (InvocationTargetException ex) {
1362: throw ex.getTargetException();
1363: }
1364: }
1365:
1366: /**
1367: * Applies the <code>postProcessAfterInitialization</code> callback of all
1368: * registered BeanPostProcessors, giving them a chance to post-process the
1369: * object obtained from FactoryBeans (for example, to auto-proxy them).
1370: * @see #applyBeanPostProcessorsAfterInitialization
1371: */
1372: protected Object postProcessObjectFromFactoryBean(Object object,
1373: String beanName) {
1374: return applyBeanPostProcessorsAfterInitialization(object,
1375: beanName);
1376: }
1377:
1378: /**
1379: * Overridden to clear FactoryBean instance cache as well.
1380: */
1381: protected void removeSingleton(String beanName) {
1382: super .removeSingleton(beanName);
1383: this .factoryBeanInstanceCache.remove(beanName);
1384: }
1385:
1386: //---------------------------------------------------------------------
1387: // Template methods to be implemented by subclasses
1388: //---------------------------------------------------------------------
1389:
1390: /**
1391: * Find bean instances that match the required type.
1392: * Called during autowiring for the specified bean.
1393: * <p>If a subclass cannot obtain information about bean names by type,
1394: * a corresponding exception should be thrown.
1395: * @param beanName the name of the bean that is about to be wired
1396: * @param requiredType the type of the autowired property or argument
1397: * @return a Map of candidate names and candidate instances that match
1398: * the required type (never <code>null</code>)
1399: * @throws BeansException in case of errors
1400: * @see #autowireByType
1401: * @see #autowireConstructor
1402: */
1403: protected Map findAutowireCandidates(String beanName,
1404: Class requiredType) throws BeansException {
1405: Map result = findMatchingBeans(requiredType);
1406: return (result != null ? result : Collections.EMPTY_MAP);
1407: }
1408:
1409: /**
1410: * Find bean instances that match the required type. Called by autowiring.
1411: * @param requiredType the type of the beans to look up
1412: * @return a Map of bean names and bean instances that match the required type,
1413: * or <code>null</code> if none found
1414: * @throws BeansException in case of errors
1415: * @deprecated as of Spring 2.0.1: Override <code>findAutowireCandidates</code> instead
1416: */
1417: protected Map findMatchingBeans(Class requiredType)
1418: throws BeansException {
1419: throw new FatalBeanException(
1420: "Bean lookup by type not supported by this factory");
1421: }
1422:
1423: //---------------------------------------------------------------------
1424: // Inner classes that serve as internal helpers
1425: //---------------------------------------------------------------------
1426:
1427: /**
1428: * Subclass of ConstructorResolver that delegates to surrounding
1429: * AbstractAutowireCapableBeanFactory facilities.
1430: */
1431: private class ConstructorResolverAdapter extends
1432: ConstructorResolver {
1433:
1434: public ConstructorResolverAdapter() {
1435: super (AbstractAutowireCapableBeanFactory.this ,
1436: getInstantiationStrategy());
1437: }
1438:
1439: protected Map findAutowireCandidates(String beanName,
1440: Class requiredType) throws BeansException {
1441: return AbstractAutowireCapableBeanFactory.this
1442: .findAutowireCandidates(beanName, requiredType);
1443: }
1444: }
1445:
1446: }
|