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