Save This Page
Home » spring-framework-2.5.5-with-dependencies » org.springframework » beans » factory » support » [javadoc | source]
    1   /*
    2    * Copyright 2002-2008 the original author or authors.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.springframework.beans.factory.support;
   18   
   19   import java.beans.PropertyEditor;
   20   import java.util.ArrayList;
   21   import java.util.Arrays;
   22   import java.util.Collections;
   23   import java.util.HashMap;
   24   import java.util.HashSet;
   25   import java.util.Iterator;
   26   import java.util.LinkedHashSet;
   27   import java.util.List;
   28   import java.util.Map;
   29   import java.util.Set;
   30   
   31   import org.springframework.beans.BeanUtils;
   32   import org.springframework.beans.BeanWrapper;
   33   import org.springframework.beans.BeansException;
   34   import org.springframework.beans.PropertyEditorRegistrar;
   35   import org.springframework.beans.PropertyEditorRegistry;
   36   import org.springframework.beans.PropertyEditorRegistrySupport;
   37   import org.springframework.beans.SimpleTypeConverter;
   38   import org.springframework.beans.TypeConverter;
   39   import org.springframework.beans.factory.BeanCreationException;
   40   import org.springframework.beans.factory.BeanCurrentlyInCreationException;
   41   import org.springframework.beans.factory.BeanDefinitionStoreException;
   42   import org.springframework.beans.factory.BeanFactory;
   43   import org.springframework.beans.factory.BeanFactoryUtils;
   44   import org.springframework.beans.factory.BeanIsAbstractException;
   45   import org.springframework.beans.factory.BeanIsNotAFactoryException;
   46   import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
   47   import org.springframework.beans.factory.CannotLoadBeanClassException;
   48   import org.springframework.beans.factory.DisposableBean;
   49   import org.springframework.beans.factory.FactoryBean;
   50   import org.springframework.beans.factory.NoSuchBeanDefinitionException;
   51   import org.springframework.beans.factory.ObjectFactory;
   52   import org.springframework.beans.factory.SmartFactoryBean;
   53   import org.springframework.beans.factory.config.BeanDefinition;
   54   import org.springframework.beans.factory.config.BeanPostProcessor;
   55   import org.springframework.beans.factory.config.ConfigurableBeanFactory;
   56   import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
   57   import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
   58   import org.springframework.beans.factory.config.Scope;
   59   import org.springframework.core.CollectionFactory;
   60   import org.springframework.core.DecoratingClassLoader;
   61   import org.springframework.core.NamedThreadLocal;
   62   import org.springframework.util.Assert;
   63   import org.springframework.util.ClassUtils;
   64   import org.springframework.util.StringUtils;
   65   
   66   /**
   67    * Abstract base class for {@link org.springframework.beans.factory.BeanFactory}
   68    * implementations, providing the full capabilities of the
   69    * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} SPI.
   70    * Does <i>not</i> assume a listable bean factory: can therefore also be used
   71    * as base class for bean factory implementations which obtain bean definitions
   72    * from some backend resource (where bean definition access is an expensive operation).
   73    *
   74    * <p>This class provides a singleton cache (through its base class
   75    * {@link org.springframework.beans.factory.support.DefaultSingletonBeanRegistry},
   76    * singleton/prototype determination, {@link org.springframework.beans.factory.FactoryBean}
   77    * handling, aliases, bean definition merging for child bean definitions,
   78    * and bean destruction ({@link org.springframework.beans.factory.DisposableBean}
   79    * interface, custom destroy methods). Furthermore, it can manage a bean factory
   80    * hierarchy (delegating to the parent in case of an unknown bean), through implementing
   81    * the {@link org.springframework.beans.factory.HierarchicalBeanFactory} interface.
   82    *
   83    * <p>The main template methods to be implemented by subclasses are
   84    * {@link #getBeanDefinition} and {@link #createBean}, retrieving a bean definition
   85    * for a given bean name and creating a bean instance for a given bean definition,
   86    * respectively. Default implementations of those operations can be found in
   87    * {@link DefaultListableBeanFactory} and {@link AbstractAutowireCapableBeanFactory}.
   88    *
   89    * @author Rod Johnson
   90    * @author Juergen Hoeller
   91    * @since 15 April 2001
   92    * @see #getBeanDefinition
   93    * @see #createBean
   94    * @see AbstractAutowireCapableBeanFactory#createBean
   95    * @see DefaultListableBeanFactory#getBeanDefinition
   96    */
   97   public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
   98   
   99   	/** Parent bean factory, for bean inheritance support */
  100   	private BeanFactory parentBeanFactory;
  101   
  102   	/** ClassLoader to resolve bean class names with, if necessary */
  103   	private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
  104   
  105   	/** ClassLoader to temporarily resolve bean class names with, if necessary */
  106   	private ClassLoader tempClassLoader;
  107   
  108   	/** Whether to cache bean metadata or rather reobtain it for every access */
  109   	private boolean cacheBeanMetadata = true;
  110   
  111   	/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
  112   	private final Set propertyEditorRegistrars = new LinkedHashSet(4);
  113   
  114   	/** Custom PropertyEditors to apply to the beans of this factory */
  115   	private final Map customEditors = new HashMap(4);
  116   
  117   	/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
  118   	private TypeConverter typeConverter;
  119   
  120   	/** BeanPostProcessors to apply in createBean */
  121   	private final List beanPostProcessors = new ArrayList();
  122   
  123   	/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
  124   	private boolean hasInstantiationAwareBeanPostProcessors;
  125   
  126   	/** Indicates whether any DestructionAwareBeanPostProcessors have been registered */
  127   	private boolean hasDestructionAwareBeanPostProcessors;
  128   
  129   	/** Map from scope identifier String to corresponding Scope */
  130   	private final Map scopes = new HashMap();
  131   
  132   	/** Map from bean name to merged RootBeanDefinition */
  133   	private final Map mergedBeanDefinitions = CollectionFactory.createConcurrentMapIfPossible(16);
  134   
  135   	/** Names of beans that have already been created at least once */
  136   	private final Set alreadyCreated = Collections.synchronizedSet(new HashSet());
  137   
  138   	/** Names of beans that are currently in creation */
  139   	private final ThreadLocal prototypesCurrentlyInCreation =
  140   			new NamedThreadLocal("Prototype beans currently in creation");
  141   
  142   
  143   	/**
  144   	 * Create a new AbstractBeanFactory.
  145   	 */
  146   	public AbstractBeanFactory() {
  147   	}
  148   
  149   	/**
  150   	 * Create a new AbstractBeanFactory with the given parent.
  151   	 * @param parentBeanFactory parent bean factory, or <code>null</code> if none
  152   	 * @see #getBean
  153   	 */
  154   	public AbstractBeanFactory(BeanFactory parentBeanFactory) {
  155   		this.parentBeanFactory = parentBeanFactory;
  156   	}
  157   
  158   
  159   	//---------------------------------------------------------------------
  160   	// Implementation of BeanFactory interface
  161   	//---------------------------------------------------------------------
  162   
  163   	public Object getBean(String name) throws BeansException {
  164   		return getBean(name, null, null);
  165   	}
  166   		
  167   	public Object getBean(String name, Class requiredType) throws BeansException {
  168   		return getBean(name, requiredType, null);
  169   	}
  170   
  171   	public Object getBean(String name, Object[] args) throws BeansException {
  172   		return getBean(name, null, args);
  173   	}
  174   
  175   	/**
  176   	 * Return an instance, which may be shared or independent, of the specified bean.
  177   	 * @param name the name of the bean to retrieve
  178   	 * @param requiredType the required type of the bean to retrieve
  179   	 * @param args arguments to use if creating a prototype using explicit arguments to a
  180   	 * static factory method. It is invalid to use a non-null args value in any other case.
  181   	 * @return an instance of the bean
  182   	 * @throws BeansException if the bean could not be created
  183   	 */
  184   	public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
  185   		return doGetBean(name, requiredType, args, false);
  186   	}
  187   
  188   	/**
  189   	 * Return an instance, which may be shared or independent, of the specified bean.
  190   	 * @param name the name of the bean to retrieve
  191   	 * @param requiredType the required type of the bean to retrieve
  192   	 * @param args arguments to use if creating a prototype using explicit arguments to a
  193   	 * static factory method. It is invalid to use a non-null args value in any other case.
  194   	 * @param typeCheckOnly whether the instance is obtained for a type check,
  195   	 * not for actual use
  196   	 * @return an instance of the bean
  197   	 * @throws BeansException if the bean could not be created
  198   	 */
  199   	protected Object doGetBean(
  200   			final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
  201   
  202   		final String beanName = transformedBeanName(name);
  203   		Object bean = null;
  204   
  205   		// Eagerly check singleton cache for manually registered singletons.
  206   		Object sharedInstance = getSingleton(beanName);
  207   		if (sharedInstance != null) {
  208   			if (logger.isDebugEnabled()) {
  209   				if (isSingletonCurrentlyInCreation(beanName)) {
  210   					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
  211   							"' that is not fully initialized yet - a consequence of a circular reference");
  212   				}
  213   				else {
  214   					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
  215   				}
  216   			}
  217   			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
  218   		}
  219   
  220   		else {
  221   			// Fail if we're already creating this bean instance:
  222   			// We're assumably within a circular reference.
  223   			if (isPrototypeCurrentlyInCreation(beanName)) {
  224   				throw new BeanCurrentlyInCreationException(beanName);
  225   			}
  226   
  227   			// Check if bean definition exists in this factory.
  228   			BeanFactory parentBeanFactory = getParentBeanFactory();
  229   			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  230   				// Not found -> check parent.
  231   				String nameToLookup = originalBeanName(name);
  232   				if (args != null) {
  233   					// Delegation to parent with explicit args.
  234   					return parentBeanFactory.getBean(nameToLookup, args);
  235   				}
  236   				else {
  237   					// No args -> delegate to standard getBean method.
  238   					return parentBeanFactory.getBean(nameToLookup, requiredType);
  239   				}
  240   			}
  241   
  242   			if (!typeCheckOnly) {
  243   				markBeanAsCreated(beanName);
  244   			}
  245   
  246   			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  247   			checkMergedBeanDefinition(mbd, beanName, args);
  248   
  249   			// Guarantee initialization of beans that the current bean depends on.
  250   			String[] dependsOn = mbd.getDependsOn();
  251   			if (dependsOn != null) {
  252   				for (int i = 0; i < dependsOn.length; i++) {
  253   					String dependsOnBean = dependsOn[i];
  254   					getBean(dependsOnBean);
  255   					registerDependentBean(dependsOnBean, beanName);
  256   				}
  257   			}
  258   
  259   			// Create bean instance.
  260   			if (mbd.isSingleton()) {
  261   				sharedInstance = getSingleton(beanName, new ObjectFactory() {
  262   					public Object getObject() throws BeansException {
  263   						try {
  264   							return createBean(beanName, mbd, args);
  265   						}
  266   						catch (BeansException ex) {
  267   							// Explicitly remove instance from singleton cache: It might have been put there
  268   							// eagerly by the creation process, to allow for circular reference resolution.
  269   							// Also remove any beans that received a temporary reference to the bean.
  270   							destroySingleton(beanName);
  271   							throw ex;
  272   						}
  273   					}
  274   				});
  275   				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
  276   			}
  277   
  278   			else if (mbd.isPrototype()) {
  279   				// It's a prototype -> create a new instance.
  280   				Object prototypeInstance = null;
  281   				try {
  282   					beforePrototypeCreation(beanName);
  283   					prototypeInstance = createBean(beanName, mbd, args);
  284   				}
  285   				finally {
  286   					afterPrototypeCreation(beanName);
  287   				}
  288   				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  289   			}
  290   
  291   			else {
  292   				String scopeName = mbd.getScope();
  293   				final Scope scope = (Scope) this.scopes.get(scopeName);
  294   				if (scope == null) {
  295   					throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
  296   				}
  297   				try {
  298   					Object scopedInstance = scope.get(beanName, new ObjectFactory() {
  299   						public Object getObject() throws BeansException {
  300   							beforePrototypeCreation(beanName);
  301   							try {
  302   								return createBean(beanName, mbd, args);
  303   							}
  304   							finally {
  305   								afterPrototypeCreation(beanName);
  306   							}
  307   						}
  308   					});
  309   					bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
  310   				}
  311   				catch (IllegalStateException ex) {
  312   					throw new BeanCreationException(beanName,
  313   							"Scope '" + scopeName + "' is not active for the current thread; " +
  314   							"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
  315   							ex);
  316   				}
  317   			}
  318   		}
  319   
  320   		// Check if required type matches the type of the actual bean instance.
  321   		if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
  322   			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
  323   		}
  324   		return bean;
  325   	}
  326   
  327   	public boolean containsBean(String name) {
  328   		String beanName = transformedBeanName(name);
  329   		if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
  330   			return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
  331   		}
  332   		// Not found -> check parent.
  333   		BeanFactory parentBeanFactory = getParentBeanFactory();
  334   		return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
  335   	}
  336   
  337   	public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
  338   		String beanName = transformedBeanName(name);
  339   
  340   		Object beanInstance = getSingleton(beanName, false);
  341   		if (beanInstance != null) {
  342   			if (beanInstance instanceof FactoryBean) {
  343   				return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean) beanInstance).isSingleton());
  344   			}
  345   			else {
  346   				return !BeanFactoryUtils.isFactoryDereference(name);
  347   			}
  348   		}
  349   
  350   		else {
  351   			// No singleton instance found -> check bean definition.
  352   			BeanFactory parentBeanFactory = getParentBeanFactory();
  353   			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  354   				// No bean definition found in this factory -> delegate to parent.
  355   				return parentBeanFactory.isSingleton(originalBeanName(name));
  356   			}
  357   
  358   			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  359   
  360   			// In case of FactoryBean, return singleton status of created object if not a dereference.
  361   			if (mbd.isSingleton()) {
  362   				if (isFactoryBean(beanName, mbd)) {
  363   					if (BeanFactoryUtils.isFactoryDereference(name)) {
  364   						return true;
  365   					}
  366   					FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
  367   					return factoryBean.isSingleton();
  368   				}
  369   				else {
  370   					return !BeanFactoryUtils.isFactoryDereference(name);
  371   				}
  372   			}
  373   			else {
  374   				return false;
  375   			}
  376   		}
  377   	}
  378   
  379   	public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
  380   		String beanName = transformedBeanName(name);
  381   
  382   		BeanFactory parentBeanFactory = getParentBeanFactory();
  383   		if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  384   			// No bean definition found in this factory -> delegate to parent.
  385   			return parentBeanFactory.isPrototype(originalBeanName(name));
  386   		}
  387   
  388   		RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  389   		if (mbd.isPrototype()) {
  390   			// In case of FactoryBean, return singleton status of created object if not a dereference.
  391   			return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName, mbd));
  392   		}
  393   		else {
  394   			// Singleton or scoped - not a prototype.
  395   			// However, FactoryBean may still produce a prototype object...
  396   			if (BeanFactoryUtils.isFactoryDereference(name)) {
  397   				return false;
  398   			}
  399   			if (isFactoryBean(beanName, mbd)) {
  400   				FactoryBean factoryBean = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
  401   				return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean) factoryBean).isPrototype()) ||
  402   						!factoryBean.isSingleton());
  403   			}
  404   			else {
  405   				return false;
  406   			}
  407   		}
  408   	}
  409   
  410   	public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException {
  411   		String beanName = transformedBeanName(name);
  412   		Class typeToMatch = (targetType != null ? targetType : Object.class);
  413   
  414   		// Check manually registered singletons.
  415   		Object beanInstance = getSingleton(beanName, false);
  416   		if (beanInstance != null) {
  417   			if (beanInstance instanceof FactoryBean) {
  418   				if (!BeanFactoryUtils.isFactoryDereference(name)) {
  419   					Class type = getTypeForFactoryBean((FactoryBean) beanInstance);
  420   					return (type != null && typeToMatch.isAssignableFrom(type));
  421   				}
  422   				else {
  423   					return typeToMatch.isAssignableFrom(beanInstance.getClass())					;
  424   				}
  425   			}
  426   			else {
  427   				return !BeanFactoryUtils.isFactoryDereference(name) &&
  428   						typeToMatch.isAssignableFrom(beanInstance.getClass());
  429   			}
  430   		}
  431   
  432   		else {
  433   			// No singleton instance found -> check bean definition.
  434   			BeanFactory parentBeanFactory = getParentBeanFactory();
  435   			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  436   				// No bean definition found in this factory -> delegate to parent.
  437   				return parentBeanFactory.isTypeMatch(originalBeanName(name), targetType);
  438   			}
  439   
  440   			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  441   			Class beanClass = predictBeanType(beanName, mbd, new Class[] {FactoryBean.class, typeToMatch});
  442   			if (beanClass == null) {
  443   				return false;
  444   			}
  445   
  446   			// Check bean class whether we're dealing with a FactoryBean.
  447   			if (FactoryBean.class.isAssignableFrom(beanClass)) {
  448   				if (!BeanFactoryUtils.isFactoryDereference(name)) {
  449   					// If it's a FactoryBean, we want to look at what it creates, not the factory class.
  450   					Class type = getTypeForFactoryBean(beanName, mbd);
  451   					return (type != null && typeToMatch.isAssignableFrom(type));
  452   				}
  453   				else {
  454   					return typeToMatch.isAssignableFrom(beanClass);
  455   				}
  456   			}
  457   			else {
  458   				return !BeanFactoryUtils.isFactoryDereference(name) &&
  459   						typeToMatch.isAssignableFrom(beanClass);
  460   			}
  461   		}
  462   	}
  463   
  464   	public Class getType(String name) throws NoSuchBeanDefinitionException {
  465   		String beanName = transformedBeanName(name);
  466   
  467   		// Check manually registered singletons.
  468   		Object beanInstance = getSingleton(beanName, false);
  469   		if (beanInstance != null) {
  470   			if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
  471   				return getTypeForFactoryBean((FactoryBean) beanInstance);
  472   			}
  473   			else {
  474   				return beanInstance.getClass();
  475   			}
  476   		}
  477   
  478   		else {
  479   			// No singleton instance found -> check bean definition.
  480   			BeanFactory parentBeanFactory = getParentBeanFactory();
  481   			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
  482   				// No bean definition found in this factory -> delegate to parent.
  483   				return parentBeanFactory.getType(originalBeanName(name));
  484   			}
  485   
  486   			RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  487   			Class beanClass = predictBeanType(beanName, mbd, null);
  488   
  489   			// Check bean class whether we're dealing with a FactoryBean.
  490   			if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) {
  491   				if (!BeanFactoryUtils.isFactoryDereference(name)) {
  492   					// If it's a FactoryBean, we want to look at what it creates, not the factory class.
  493   					return getTypeForFactoryBean(beanName, mbd);
  494   				}
  495   				else {
  496   					return beanClass;
  497   				}
  498   			}
  499   			else {
  500   				return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null);
  501   			}
  502   		}
  503   	}
  504   
  505   	public String[] getAliases(String name) {
  506   		String beanName = transformedBeanName(name);
  507   		List aliases = new ArrayList();
  508   		boolean factoryPrefix = name.startsWith(FACTORY_BEAN_PREFIX);
  509   		String fullBeanName = beanName;
  510   		if (factoryPrefix) {
  511   			fullBeanName = FACTORY_BEAN_PREFIX + beanName;
  512   		}
  513   		if (!fullBeanName.equals(name)) {
  514   			aliases.add(fullBeanName);
  515   		}
  516   		String[] retrievedAliases = super.getAliases(beanName);
  517   		for (int i = 0; i < retrievedAliases.length; i++) {
  518   			String alias = (factoryPrefix ? FACTORY_BEAN_PREFIX : "") + retrievedAliases[i];
  519   			if (!alias.equals(name)) {
  520   				aliases.add(alias);
  521   			}
  522   		}
  523   		if (!containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
  524   			BeanFactory parentBeanFactory = getParentBeanFactory();
  525   			if (parentBeanFactory != null) {
  526   				aliases.addAll(Arrays.asList(parentBeanFactory.getAliases(fullBeanName)));
  527   			}
  528   		}
  529   		return StringUtils.toStringArray(aliases);
  530   	}
  531   
  532   
  533   	//---------------------------------------------------------------------
  534   	// Implementation of HierarchicalBeanFactory interface
  535   	//---------------------------------------------------------------------
  536   
  537   	public BeanFactory getParentBeanFactory() {
  538   		return this.parentBeanFactory;
  539   	}
  540   
  541   	public boolean containsLocalBean(String name) {
  542   		String beanName = transformedBeanName(name);
  543   		return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) &&
  544   				(!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName)));
  545   	}
  546   
  547   
  548   	//---------------------------------------------------------------------
  549   	// Implementation of ConfigurableBeanFactory interface
  550   	//---------------------------------------------------------------------
  551   
  552   	public void setParentBeanFactory(BeanFactory parentBeanFactory) {
  553   		if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) {
  554   			throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory);
  555   		}
  556   		this.parentBeanFactory = parentBeanFactory;
  557   	}
  558   
  559   	public void setBeanClassLoader(ClassLoader beanClassLoader) {
  560   		this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
  561   	}
  562   
  563   	public ClassLoader getBeanClassLoader() {
  564   		return this.beanClassLoader;
  565   	}
  566   
  567   	public void setTempClassLoader(ClassLoader tempClassLoader) {
  568   		this.tempClassLoader = tempClassLoader;
  569   	}
  570   
  571   	public ClassLoader getTempClassLoader() {
  572   		return this.tempClassLoader;
  573   	}
  574   
  575   	public void setCacheBeanMetadata(boolean cacheBeanMetadata) {
  576   		this.cacheBeanMetadata = cacheBeanMetadata;
  577   	}
  578   
  579   	public boolean isCacheBeanMetadata() {
  580   		return this.cacheBeanMetadata;
  581   	}
  582   
  583   	public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
  584   		Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
  585   		this.propertyEditorRegistrars.add(registrar);
  586   	}
  587   
  588   	/**
  589   	 * Return the set of PropertyEditorRegistrars.
  590   	 */
  591   	public Set getPropertyEditorRegistrars() {
  592   		return this.propertyEditorRegistrars;
  593   	}
  594   
  595   	public void registerCustomEditor(Class requiredType, Class propertyEditorClass) {
  596   		Assert.notNull(requiredType, "Required type must not be null");
  597   		Assert.isAssignable(PropertyEditor.class, propertyEditorClass);
  598   		this.customEditors.put(requiredType, propertyEditorClass);
  599   	}
  600   
  601   	public void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor) {
  602   		Assert.notNull(requiredType, "Required type must not be null");
  603   		Assert.notNull(propertyEditor, "PropertyEditor must not be null");
  604   		this.customEditors.put(requiredType, propertyEditor);
  605   	}
  606   
  607   	/**
  608   	 * Return the map of custom editors, with Classes as keys
  609   	 * and PropertyEditor instances or PropertyEditor classes as values.
  610   	 */
  611   	public Map getCustomEditors() {
  612   		return this.customEditors;
  613   	}
  614   
  615   	public void setTypeConverter(TypeConverter typeConverter) {
  616   		this.typeConverter = typeConverter;
  617   	}
  618   
  619   	/**
  620   	 * Return the custom TypeConverter to use, if any.
  621   	 * @return the custom TypeConverter, or <code>null</code> if none specified
  622   	 */
  623   	protected TypeConverter getCustomTypeConverter() {
  624   		return this.typeConverter;
  625   	}
  626   
  627   	public TypeConverter getTypeConverter() {
  628   		TypeConverter customConverter = getCustomTypeConverter();
  629   		if (customConverter != null) {
  630   			return customConverter;
  631   		}
  632   		else {
  633   			// Build default TypeConverter, registering custom editors.
  634   			SimpleTypeConverter typeConverter = new SimpleTypeConverter();
  635   			registerCustomEditors(typeConverter);
  636   			return typeConverter;
  637   		}
  638   	}
  639   
  640   	public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
  641   		Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
  642   		this.beanPostProcessors.add(beanPostProcessor);
  643   		if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
  644   			this.hasInstantiationAwareBeanPostProcessors = true;
  645   		}
  646   		if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
  647   			this.hasDestructionAwareBeanPostProcessors = true;
  648   		}
  649   	}
  650   
  651   	public int getBeanPostProcessorCount() {
  652   		return this.beanPostProcessors.size();
  653   	}
  654   
  655   	/**
  656   	 * Return the list of BeanPostProcessors that will get applied
  657   	 * to beans created with this factory.
  658   	 */
  659   	public List getBeanPostProcessors() {
  660   		return this.beanPostProcessors;
  661   	}
  662   
  663   	/**
  664   	 * Return whether this factory holds a InstantiationAwareBeanPostProcessor
  665   	 * that will get applied to singleton beans on shutdown.
  666   	 * @see #addBeanPostProcessor
  667   	 * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
  668   	 */
  669   	protected boolean hasInstantiationAwareBeanPostProcessors() {
  670   		return this.hasInstantiationAwareBeanPostProcessors;
  671   	}
  672   
  673   	/**
  674   	 * Return whether this factory holds a DestructionAwareBeanPostProcessor
  675   	 * that will get applied to singleton beans on shutdown.
  676   	 * @see #addBeanPostProcessor
  677   	 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
  678   	 */
  679   	protected boolean hasDestructionAwareBeanPostProcessors() {
  680   		return this.hasDestructionAwareBeanPostProcessors;
  681   	}
  682   
  683   	public void registerScope(String scopeName, Scope scope) {
  684   		Assert.notNull(scopeName, "Scope identifier must not be null");
  685   		Assert.notNull(scope, "Scope must not be null");
  686   		if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) {
  687   			throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'");
  688   		}
  689   		this.scopes.put(scopeName, scope);
  690   	}
  691   
  692   	public String[] getRegisteredScopeNames() {
  693   		return StringUtils.toStringArray(this.scopes.keySet());
  694   	}
  695   
  696   	public Scope getRegisteredScope(String scopeName) {
  697   		Assert.notNull(scopeName, "Scope identifier must not be null");
  698   		return (Scope) this.scopes.get(scopeName);
  699   	}
  700   
  701   	public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) {
  702   		Assert.notNull(otherFactory, "BeanFactory must not be null");
  703   		setBeanClassLoader(otherFactory.getBeanClassLoader());
  704   		setCacheBeanMetadata(otherFactory.isCacheBeanMetadata());
  705   		if (otherFactory instanceof AbstractBeanFactory) {
  706   			AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory;
  707   			this.customEditors.putAll(otherAbstractFactory.customEditors);
  708   			this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars);
  709   			this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors);
  710   			this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors ||
  711   					otherAbstractFactory.hasInstantiationAwareBeanPostProcessors;
  712   			this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors ||
  713   					otherAbstractFactory.hasDestructionAwareBeanPostProcessors;
  714   			this.scopes.putAll(otherAbstractFactory.scopes);
  715   		}
  716   	}
  717   
  718   	/**
  719   	 * Return a 'merged' BeanDefinition for the given bean name,
  720   	 * merging a child bean definition with its parent if necessary.
  721   	 * <p>This <code>getMergedBeanDefinition</code> considers bean definition
  722   	 * in ancestors as well.
  723   	 * @param name the name of the bean to retrieve the merged definition for
  724   	 * (may be an alias)
  725   	 * @return a (potentially merged) RootBeanDefinition for the given bean
  726   	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
  727   	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
  728   	 */
  729   	public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
  730   		String beanName = transformedBeanName(name);
  731   
  732   		// Efficiently check whether bean definition exists in this factory.
  733   		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
  734   			return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
  735   		}
  736   		// Resolve merged bean definition locally.
  737   		return getMergedLocalBeanDefinition(beanName);
  738   	}
  739   
  740   	public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
  741   		String beanName = transformedBeanName(name);
  742   
  743   		Object beanInstance = getSingleton(beanName, false);
  744   		if (beanInstance != null) {
  745   			return (beanInstance instanceof FactoryBean);
  746   		}
  747   
  748   		// No singleton instance found -> check bean definition.
  749   		if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
  750   			// No bean definition found in this factory -> delegate to parent.
  751   			return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
  752   		}
  753   
  754   		return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
  755   	}
  756   
  757   	/**
  758   	 * Callback before prototype creation.
  759   	 * <p>The default implementation register the prototype as currently in creation.
  760   	 * @param beanName the name of the prototype about to be created
  761   	 * @see #isPrototypeCurrentlyInCreation
  762   	 */
  763   	protected void beforePrototypeCreation(String beanName) {
  764   		Object curVal = this.prototypesCurrentlyInCreation.get();
  765   		if (curVal == null) {
  766   			this.prototypesCurrentlyInCreation.set(beanName);
  767   		}
  768   		else if (curVal instanceof String) {
  769   			Set beanNameSet = new HashSet(2);
  770   			beanNameSet.add(curVal);
  771   			beanNameSet.add(beanName);
  772   			this.prototypesCurrentlyInCreation.set(beanNameSet);
  773   		}
  774   		else {
  775   			Set beanNameSet = (Set) curVal;
  776   			beanNameSet.add(beanName);
  777   		}
  778   	}
  779   
  780   	/**
  781   	 * Callback after prototype creation.
  782   	 * <p>The default implementation marks the prototype as not in creation anymore.
  783   	 * @param beanName the name of the prototype that has been created
  784   	 * @see #isPrototypeCurrentlyInCreation
  785   	 */
  786   	protected void afterPrototypeCreation(String beanName) {
  787   		Object curVal = this.prototypesCurrentlyInCreation.get();
  788   		if (curVal instanceof String) {
  789   			this.prototypesCurrentlyInCreation.set(null);
  790   		}
  791   		else if (curVal instanceof Set) {
  792   			Set beanNameSet = (Set) curVal;
  793   			beanNameSet.remove(beanName);
  794   			if (beanNameSet.isEmpty()) {
  795   				this.prototypesCurrentlyInCreation.set(null);
  796   			}
  797   		}
  798   	}
  799   
  800   	/**
  801   	 * Return whether the specified prototype bean is currently in creation
  802   	 * (within the current thread).
  803   	 * @param beanName the name of the bean
  804   	 */
  805   	protected final boolean isPrototypeCurrentlyInCreation(String beanName) {
  806   		Object curVal = this.prototypesCurrentlyInCreation.get();
  807   		return (curVal != null &&
  808   				(curVal.equals(beanName) || (curVal instanceof Set && ((Set) curVal).contains(beanName))));
  809   	}
  810   
  811   	public boolean isCurrentlyInCreation(String beanName) {
  812   		return isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName);
  813   	}
  814   
  815   	public void destroyBean(String beanName, Object beanInstance) {
  816   		destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
  817   	}
  818   
  819   	/**
  820   	 * Destroy the given bean instance (usually a prototype instance
  821   	 * obtained from this factory) according to the given bean definition.
  822   	 * @param beanName the name of the bean definition
  823   	 * @param beanInstance the bean instance to destroy
  824   	 * @param mbd the merged bean definition
  825   	 */
  826   	protected void destroyBean(String beanName, Object beanInstance, RootBeanDefinition mbd) {
  827   		new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors()).destroy();
  828   	}
  829   
  830   	public void destroyScopedBean(String beanName) {
  831   		RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
  832   		if (mbd.isSingleton() || mbd.isPrototype()) {
  833   			throw new IllegalArgumentException(
  834   					"Bean name '" + beanName + "' does not correspond to an object in a Scope");
  835   		}
  836   		String scopeName = mbd.getScope();
  837   		Scope scope = (Scope) this.scopes.get(scopeName);
  838   		if (scope == null) {
  839   			throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
  840   		}
  841   		Object bean = scope.remove(beanName);
  842   		if (bean != null) {
  843   			destroyBean(beanName, bean, mbd);
  844   		}
  845   	}
  846   
  847   
  848   	//---------------------------------------------------------------------
  849   	// Implementation methods
  850   	//---------------------------------------------------------------------
  851   
  852   	/**
  853   	 * Return the bean name, stripping out the factory dereference prefix if necessary,
  854   	 * and resolving aliases to canonical names.
  855   	 * @param name the user-specified name
  856   	 * @return the transformed bean name
  857   	 */
  858   	protected String transformedBeanName(String name) {
  859   		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
  860   	}
  861   
  862   	/**
  863   	 * Determine the original bean name, resolving locally defined aliases to canonical names.
  864   	 * @param name the user-specified name
  865   	 * @return the original bean name
  866   	 */
  867   	protected String originalBeanName(String name) {
  868   		String beanName = transformedBeanName(name);
  869   		if (name.startsWith(FACTORY_BEAN_PREFIX)) {
  870   			beanName = FACTORY_BEAN_PREFIX + beanName;
  871   		}
  872   		return beanName;
  873   	}
  874   
  875   	/**
  876   	 * Initialize the given BeanWrapper with the custom editors registered
  877   	 * with this factory. To be called for BeanWrappers that will create
  878   	 * and populate bean instances.
  879   	 * <p>The default implementation delegates to <code>registerCustomEditors</code>.
  880   	 * Can be overridden in subclasses.
  881   	 * @param bw the BeanWrapper to initialize
  882   	 * @see #registerCustomEditors
  883   	 */
  884   	protected void initBeanWrapper(BeanWrapper bw) {
  885   		registerCustomEditors(bw);
  886   	}
  887   
  888   	/**
  889   	 * Initialize the given PropertyEditorRegistry with the custom editors
  890   	 * registered with this BeanFactory.
  891   	 * <p>To be called for BeanWrappers that will create and populate bean
  892   	 * instances, and for SimpleTypeConverter used for constructor argument
  893   	 * and factory method type conversion.
  894   	 * @param registry the PropertyEditorRegistry to initialize
  895   	 */
  896   	protected void registerCustomEditors(PropertyEditorRegistry registry) {
  897   		PropertyEditorRegistrySupport registrySupport =
  898   				(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
  899   		if (registrySupport != null) {
  900   			registrySupport.useConfigValueEditors();
  901   		}
  902   		if (!this.propertyEditorRegistrars.isEmpty()) {
  903   			for (Iterator it = this.propertyEditorRegistrars.iterator(); it.hasNext();) {
  904   				PropertyEditorRegistrar registrar = (PropertyEditorRegistrar) it.next();
  905   				try {
  906   					registrar.registerCustomEditors(registry);
  907   				}
  908   				catch (BeanCreationException ex) {
  909   					Throwable rootCause = ex.getMostSpecificCause();
  910   					if (rootCause instanceof BeanCurrentlyInCreationException) {
  911   						BeanCreationException bce = (BeanCreationException) rootCause;
  912   						if (isCurrentlyInCreation(bce.getBeanName())) {
  913   							if (logger.isDebugEnabled()) {
  914   								logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
  915   										"] failed because it tried to obtain currently created bean '" + ex.getBeanName() +
  916   										"': " + ex.getMessage());
  917   							}
  918   							onSuppressedException(ex);
  919   							continue;
  920   						}
  921   					}
  922   					throw ex;
  923   				}
  924   			}
  925   		}
  926   		if (!this.customEditors.isEmpty()) {
  927   			for (Iterator it = this.customEditors.entrySet().iterator(); it.hasNext();) {
  928   				Map.Entry entry = (Map.Entry) it.next();
  929   				Class requiredType = (Class) entry.getKey();
  930   				Object value = entry.getValue();
  931   				if (value instanceof PropertyEditor) {
  932   					PropertyEditor editor = (PropertyEditor) value;
  933   					// Register the editor as shared instance, if possible,
  934   					// to make it clear that it might be used concurrently.
  935   					if (registrySupport != null) {
  936   						registrySupport.registerSharedEditor(requiredType, editor);
  937   					}
  938   					else {
  939   						registry.registerCustomEditor(requiredType, editor);
  940   					}
  941   				}
  942   				else if (value instanceof Class) {
  943   					Class editorClass = (Class) value;
  944   					registry.registerCustomEditor(requiredType, (PropertyEditor) BeanUtils.instantiateClass(editorClass));
  945   				}
  946   				else {
  947   					throw new IllegalStateException("Illegal custom editor value type: " + value.getClass().getName());
  948   				}
  949   			}
  950   		}
  951   	}
  952   
  953   
  954   	/**
  955   	 * Return a merged RootBeanDefinition, traversing the parent bean definition
  956   	 * if the specified bean corresponds to a child bean definition.
  957   	 * @param beanName the name of the bean to retrieve the merged definition for
  958   	 * @return a (potentially merged) RootBeanDefinition for the given bean
  959   	 * @throws NoSuchBeanDefinitionException if there is no bean with the given name
  960   	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
  961   	 */
  962   	protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
  963   		// Quick check on the concurrent map first, with minimal locking.
  964   		RootBeanDefinition mbd = (RootBeanDefinition) this.mergedBeanDefinitions.get(beanName);
  965   		if (mbd != null) {
  966   			return mbd;
  967   		}
  968   		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
  969   	}
  970   
  971   	/**
  972   	 * Return a RootBeanDefinition for the given top-level bean, by merging with
  973   	 * the parent if the given bean's definition is a child bean definition.
  974   	 * @param beanName the name of the bean definition
  975   	 * @param bd the original bean definition (Root/ChildBeanDefinition)
  976   	 * @return a (potentially merged) RootBeanDefinition for the given bean
  977   	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
  978   	 */
  979   	protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
  980   			throws BeanDefinitionStoreException {
  981   
  982   		return getMergedBeanDefinition(beanName, bd, null);
  983   	}
  984   
  985   	/**
  986   	 * Return a RootBeanDefinition for the given bean, by merging with the
  987   	 * parent if the given bean's definition is a child bean definition.
  988   	 * @param beanName the name of the bean definition
  989   	 * @param bd the original bean definition (Root/ChildBeanDefinition)
  990   	 * @param containingBd the containing bean definition in case of inner bean,
  991   	 * or <code>null</code> in case of a top-level bean
  992   	 * @return a (potentially merged) RootBeanDefinition for the given bean
  993   	 * @throws BeanDefinitionStoreException in case of an invalid bean definition
  994   	 */
  995   	protected RootBeanDefinition getMergedBeanDefinition(
  996   			String beanName, BeanDefinition bd, BeanDefinition containingBd)
  997   			throws BeanDefinitionStoreException {
  998   
  999   		synchronized (this.mergedBeanDefinitions) {
 1000   			RootBeanDefinition mbd = null;
 1001   
 1002   			// Check with full lock now in order to enforce the same merged instance.
 1003   			if (containingBd == null) {
 1004   				mbd = (RootBeanDefinition) this.mergedBeanDefinitions.get(beanName);
 1005   			}
 1006   
 1007   			if (mbd == null) {
 1008   				if (bd.getParentName() == null) {
 1009   					// Use copy of given root bean definition.
 1010   					mbd = new RootBeanDefinition(bd);
 1011   				}
 1012   				else {
 1013   					// Child bean definition: needs to be merged with parent.
 1014   					BeanDefinition pbd = null;
 1015   					try {
 1016   						String parentBeanName = transformedBeanName(bd.getParentName());
 1017   						if (!beanName.equals(parentBeanName)) {
 1018   							pbd = getMergedBeanDefinition(parentBeanName);
 1019   						}
 1020   						else {
 1021   							if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
 1022   								pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
 1023   							}
 1024   							else {
 1025   								throw new NoSuchBeanDefinitionException(bd.getParentName(),
 1026   										"Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
 1027   										"': cannot be resolved without an AbstractBeanFactory parent");
 1028   							}
 1029   						}
 1030   					}
 1031   					catch (NoSuchBeanDefinitionException ex) {
 1032   						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
 1033   								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
 1034   					}
 1035   					// Deep copy with overridden values.
 1036   					mbd = new RootBeanDefinition(pbd);
 1037   					mbd.overrideFrom(bd);
 1038   				}
 1039   
 1040   				// A bean contained in a non-singleton bean cannot be a singleton itself.
 1041   				// Let's correct this on the fly here, since this might be the result of
 1042   				// parent-child merging for the outer bean, in which case the original inner bean
 1043   				// definition will not have inherited the merged outer bean's singleton status.
 1044   				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
 1045   					mbd.setScope(containingBd.getScope());
 1046   				}
 1047   
 1048   				// Only cache the merged bean definition if we're already about to create an
 1049   				// instance of the bean, or at least have already created an instance before.
 1050   				if (containingBd == null && isCacheBeanMetadata() && isBeanEligibleForMetadataCaching(beanName)) {
 1051   					this.mergedBeanDefinitions.put(beanName, mbd);
 1052   				}
 1053   			}
 1054   
 1055   			return mbd;
 1056   		}
 1057   	}
 1058   
 1059   	/**
 1060   	 * Check the given merged bean definition,
 1061   	 * potentially throwing validation exceptions.
 1062   	 * @param mbd the merged bean definition to check
 1063   	 * @param beanName the name of the bean
 1064   	 * @param args the arguments for bean creation, if any
 1065   	 * @throws BeanDefinitionStoreException in case of validation failure
 1066   	 */
 1067   	protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
 1068   			throws BeanDefinitionStoreException {
 1069   
 1070   		// check if bean definition is not abstract
 1071   		if (mbd.isAbstract()) {
 1072   			throw new BeanIsAbstractException(beanName);
 1073   		}
 1074   
 1075   		// Check validity of the usage of the args parameter. This can
 1076   		// only be used for prototypes constructed via a factory method.
 1077   		if (args != null && !mbd.isPrototype()) {
 1078   			throw new BeanDefinitionStoreException(
 1079   					"Can only specify arguments for the getBean method when referring to a prototype bean definition");
 1080   		}
 1081   	}
 1082   
 1083   	/**
 1084   	 * Remove the merged bean definition for the specified bean,
 1085   	 * recreating it on next access.
 1086   	 * @param beanName the bean name to clear the merged definition for
 1087   	 */
 1088   	protected void clearMergedBeanDefinition(String beanName) {
 1089   		this.mergedBeanDefinitions.remove(beanName);
 1090   	}
 1091   
 1092   	/**
 1093   	 * Resolve the bean class for the specified bean definition,
 1094   	 * resolving a bean class name into a Class reference (if necessary)
 1095   	 * and storing the resolved Class in the bean definition for further use.
 1096   	 * @param mbd the merged bean definition to determine the class for
 1097   	 * @param beanName the name of the bean (for error handling purposes)
 1098   	 * @return the resolved bean class (or <code>null</code> if none)
 1099   	 * @throws CannotLoadBeanClassException if we failed to load the class
 1100   	 */
 1101   	protected Class resolveBeanClass(RootBeanDefinition mbd, String beanName) {
 1102   		return resolveBeanClass(mbd, beanName, null);
 1103   	}
 1104   
 1105   	/**
 1106   	 * Resolve the bean class for the specified bean definition,
 1107   	 * resolving a bean class name into a Class reference (if necessary)
 1108   	 * and storing the resolved Class in the bean definition for further use.
 1109   	 * @param mbd the merged bean definition to determine the class for
 1110   	 * @param beanName the name of the bean (for error handling purposes)
 1111   	 * @param typesToMatch the types to match in case of internal type matching purposes
 1112   	 * (also signals that the returned <code>Class</code> will never be exposed to application code)
 1113   	 * @return the resolved bean class (or <code>null</code> if none)
 1114   	 * @throws CannotLoadBeanClassException if we failed to load the class
 1115   	 */
 1116   	protected Class resolveBeanClass(RootBeanDefinition mbd, String beanName, Class[] typesToMatch)
 1117   			throws CannotLoadBeanClassException {
 1118   		try {
 1119   			if (mbd.hasBeanClass()) {
 1120   				return mbd.getBeanClass();
 1121   			}
 1122   			if (typesToMatch != null) {
 1123   				ClassLoader tempClassLoader = getTempClassLoader();
 1124   				if (tempClassLoader != null) {
 1125   					if (tempClassLoader instanceof DecoratingClassLoader) {
 1126   						DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
 1127   						for (int i = 0; i < typesToMatch.length; i++) {
 1128   							dcl.excludeClass(typesToMatch[i].getName());
 1129   						}
 1130   					}
 1131   					String className = mbd.getBeanClassName();
 1132   					return (className != null ? ClassUtils.forName(className, tempClassLoader) : null);
 1133   				}
 1134   			}
 1135   			return mbd.resolveBeanClass(getBeanClassLoader());
 1136   		}
 1137   		catch (ClassNotFoundException ex) {
 1138   			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
 1139   		}
 1140   		catch (LinkageError err) {
 1141   			throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
 1142   		}
 1143   	}
 1144   
 1145   
 1146   	/**
 1147   	 * Predict the eventual bean type (of the processed bean instance) for the
 1148   	 * specified bean. Called by {@link #getType} and {@link #isTypeMatch}.
 1149   	 * Does not need to handle FactoryBeans specifically, since it is only
 1150   	 * supposed to operate on the raw bean type.
 1151   	 * <p>This implementation is simplistic in that it is not able to
 1152   	 * handle factory methods and InstantiationAwareBeanPostProcessors.
 1153   	 * It only predicts the bean type correctly for a standard bean.
 1154   	 * To be overridden in subclasses, applying more sophisticated type detection.
 1155   	 * @param beanName the name of the bean
 1156   	 * @param mbd the merged bean definition to determine the type for
 1157   	 * @param typesToMatch the types to match in case of internal type matching purposes
 1158   	 * (also signals that the returned <code>Class</code> will never be exposed to application code)
 1159   	 * @return the type of the bean, or <code>null</code> if not predictable
 1160   	 */
 1161   	protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
 1162   		if (mbd.getFactoryMethodName() != null) {
 1163   			return null;
 1164   		}
 1165   		return resolveBeanClass(mbd, beanName, typesToMatch);
 1166   	}
 1167   
 1168   	/**
 1169   	 * Check whether the given bean is defined as a {@link FactoryBean}.
 1170   	 * @param beanName the name of the bean
 1171   	 * @param mbd the corresponding bean definition
 1172   	 */
 1173   	protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
 1174   		Class beanClass = predictBeanType(beanName, mbd, new Class[] {FactoryBean.class});
 1175   		return (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass));
 1176   	}
 1177   
 1178   	/**
 1179   	 * Determine the bean type for the given FactoryBean definition, as far as possible.
 1180   	 * Only called if there is no singleton instance registered for the target bean already.
 1181   	 * <p>The default implementation creates the FactoryBean via <code>getBean</code>
 1182   	 * to call its <code>getObjectType</code> method. Subclasses are encouraged to optimize
 1183   	 * this, typically by just instantiating the FactoryBean but not populating it yet,
 1184   	 * trying whether its <code>getObjectType</code> method already returns a type.
 1185   	 * If no type found, a full FactoryBean creation as performed by this implementation
 1186   	 * should be used as fallback.
 1187   	 * @param beanName the name of the bean
 1188   	 * @param mbd the merged bean definition for the bean
 1189   	 * @return the type for the bean if determinable, or <code>null</code> else
 1190   	 * @see org.springframework.beans.factory.FactoryBean#getObjectType()
 1191   	 * @see #getBean(String)
 1192   	 */
 1193   	protected Class getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) {
 1194   		if (!mbd.isSingleton()) {
 1195   			return null;
 1196   		}
 1197   		try {
 1198   			FactoryBean factoryBean =
 1199   					(FactoryBean) doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true);
 1200   			return getTypeForFactoryBean(factoryBean);
 1201   		}
 1202   		catch (BeanCreationException ex) {
 1203   			// Can only happen when getting a FactoryBean.
 1204   			if (logger.isDebugEnabled()) {
 1205   				logger.debug("Ignoring bean creation exception on FactoryBean type check: " + ex);
 1206   			}
 1207   			onSuppressedException(ex);
 1208   			return null;
 1209   		}
 1210   	}
 1211   
 1212   	/**
 1213   	 * Mark the specified bean as already created (or about to be created).
 1214   	 * <p>This allows the bean factory to optimize its caching for repeated
 1215   	 * creation of the specified bean.
 1216   	 * @param beanName the name of the bean
 1217   	 */
 1218   	protected void markBeanAsCreated(String beanName) {
 1219   		this.alreadyCreated.add(beanName);
 1220   	}
 1221   
 1222   	/**
 1223   	 * Determine whether the specified bean is eligible for having
 1224   	 * its bean definition metadata cached.
 1225   	 * @param beanName the name of the bean
 1226   	 * @return <code>true</code> if the bean's metadata may be cached
 1227   	 * at this point already
 1228   	 */
 1229   	protected boolean isBeanEligibleForMetadataCaching(String beanName) {
 1230   		return this.alreadyCreated.contains(beanName);
 1231   	}
 1232   
 1233   	/**
 1234   	 * Remove the singleton instance (if any) for the given bean name,
 1235   	 * but only if it hasn't been used for other purposes than type checking.
 1236   	 * @param beanName the name of the bean
 1237   	 * @return <code>true</code> if actually removed, <code>false</code> otherwise
 1238   	 */
 1239   	protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
 1240   		if (!this.alreadyCreated.contains(beanName)) {
 1241   			removeSingleton(beanName);
 1242   			return true;
 1243   		}
 1244   		else {
 1245   			return false;
 1246   		}
 1247   	}
 1248   
 1249   	/**
 1250   	 * Get the object for the given bean instance, either the bean
 1251   	 * instance itself or its created object in case of a FactoryBean.
 1252   	 * @param beanInstance the shared bean instance
 1253   	 * @param name name that may include factory dereference prefix
 1254   	 * @param beanName the canonical bean name
 1255   	 * @param mbd the merged bean definition
 1256   	 * @return the object to expose for the bean
 1257   	 */
 1258   	protected Object getObjectForBeanInstance(
 1259   			Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
 1260   
 1261   		// Don't let calling code try to dereference the factory if the bean isn't a factory.
 1262   		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
 1263   			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
 1264   		}
 1265   
 1266   		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
 1267   		// If it's a FactoryBean, we use it to create a bean instance, unless the
 1268   		// caller actually wants a reference to the factory.
 1269   		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
 1270   			return beanInstance;
 1271   		}
 1272   
 1273   		Object object = null;
 1274   		if (mbd == null) {
 1275   			object = getCachedObjectForFactoryBean(beanName);
 1276   		}
 1277   		if (object == null) {
 1278   			// Return bean instance from factory.
 1279   			FactoryBean factory = (FactoryBean) beanInstance;
 1280   			// Caches object obtained from FactoryBean if it is a singleton.
 1281   			if (mbd == null && containsBeanDefinition(beanName)) {
 1282   				mbd = getMergedLocalBeanDefinition(beanName);
 1283   			}
 1284   			boolean synthetic = (mbd != null && mbd.isSynthetic());
 1285   			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
 1286   		}
 1287   		return object;
 1288   	}
 1289   
 1290   	/**
 1291   	 * Determine whether the given bean name is already in use within this factory,
 1292   	 * i.e. whether there is a local bean or alias registered under this name or
 1293   	 * an inner bean created with this name.
 1294   	 * @param beanName the name to check
 1295   	 */
 1296   	public boolean isBeanNameInUse(String beanName) {
 1297   		return isAlias(beanName) || containsLocalBean(beanName) || hasDependentBean(beanName);
 1298   	}
 1299   
 1300   	/**
 1301   	 * Determine whether the given bean requires destruction on shutdown.
 1302   	 * <p>The default implementation checks the DisposableBean interface as well as
 1303   	 * a specified destroy method and registered DestructionAwareBeanPostProcessors.
 1304   	 * @param bean the bean instance to check
 1305   	 * @param mbd the corresponding bean definition
 1306   	 * @see org.springframework.beans.factory.DisposableBean
 1307   	 * @see AbstractBeanDefinition#getDestroyMethodName()
 1308   	 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
 1309   	 */
 1310   	protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
 1311   		return (bean instanceof DisposableBean || mbd.getDestroyMethodName() != null ||
 1312   				hasDestructionAwareBeanPostProcessors());
 1313   	}
 1314   
 1315   	/**
 1316   	 * Add the given bean to the list of disposable beans in this factory,
 1317   	 * registering its DisposableBean interface and/or the given destroy method
 1318   	 * to be called on factory shutdown (if applicable). Only applies to singletons.
 1319   	 * @param beanName the name of the bean
 1320   	 * @param bean the bean instance
 1321   	 * @param mbd the bean definition for the bean
 1322   	 * @see RootBeanDefinition#isSingleton
 1323   	 * @see RootBeanDefinition#getDependsOn
 1324   	 * @see #registerDisposableBean
 1325   	 * @see #registerDependentBean
 1326   	 */
 1327   	protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
 1328   		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
 1329   			if (mbd.isSingleton()) {
 1330   				// Register a DisposableBean implementation that performs all destruction
 1331   				// work for the given bean: DestructionAwareBeanPostProcessors,
 1332   				// DisposableBean interface, custom destroy method.
 1333   				registerDisposableBean(beanName,
 1334   						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors()));
 1335   			}
 1336   			else {
 1337   				// A bean with a custom scope...
 1338   				Scope scope = (Scope) this.scopes.get(mbd.getScope());
 1339   				if (scope == null) {
 1340   					throw new IllegalStateException("No Scope registered for scope '" + mbd.getScope() + "'");
 1341   				}
 1342   				scope.registerDestructionCallback(beanName,
 1343   						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors()));
 1344   			}
 1345   		}
 1346   	}
 1347   
 1348   
 1349   	//---------------------------------------------------------------------
 1350   	// Abstract methods to be implemented by subclasses
 1351   	//---------------------------------------------------------------------
 1352   
 1353   	/**
 1354   	 * Check if this bean factory contains a bean definition with the given name.
 1355   	 * Does not consider any hierarchy this factory may participate in.
 1356   	 * Invoked by <code>containsBean</code> when no cached singleton instance is found.
 1357   	 * <p>Depending on the nature of the concrete bean factory implementation,
 1358   	 * this operation might be expensive (for example, because of directory lookups
 1359   	 * in external registries). However, for listable bean factories, this usually
 1360   	 * just amounts to a local hash lookup: The operation is therefore part of the
 1361   	 * public interface there. The same implementation can serve for both this
 1362   	 * template method and the public interface method in that case.
 1363   	 * @param beanName the name of the bean to look for
 1364   	 * @return if this bean factory contains a bean definition with the given name
 1365   	 * @see #containsBean
 1366   	 * @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition
 1367   	 */
 1368   	protected abstract boolean containsBeanDefinition(String beanName);
 1369   
 1370   	/**
 1371   	 * Return the bean definition for the given bean name.
 1372   	 * Subclasses should normally implement caching, as this method is invoked
 1373   	 * by this class every time bean definition metadata is needed.
 1374   	 * <p>Depending on the nature of the concrete bean factory implementation,
 1375   	 * this operation might be expensive (for example, because of directory lookups
 1376   	 * in external registries). However, for listable bean factories, this usually
 1377   	 * just amounts to a local hash lookup: The operation is therefore part of the
 1378   	 * public interface there. The same implementation can serve for both this
 1379   	 * template method and the public interface method in that case.
 1380   	 * @param beanName the name of the bean to find a definition for
 1381   	 * @return the BeanDefinition for this prototype name (never <code>null</code>)
 1382   	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
 1383   	 * if the bean definition cannot be resolved
 1384   	 * @throws BeansException in case of errors
 1385   	 * @see RootBeanDefinition
 1386   	 * @see ChildBeanDefinition
 1387   	 * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
 1388   	 */
 1389   	protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
 1390   
 1391   	/**
 1392   	 * Create a bean instance for the given bean definition.
 1393   	 * The bean definition will already have been merged with the parent
 1394   	 * definition in case of a child definition.
 1395   	 * <p>All the other methods in this class invoke this method, although
 1396   	 * beans may be cached after being instantiated by this method. All bean
 1397   	 * instantiation within this class is performed by this method.
 1398   	 * @param beanName the name of the bean
 1399   	 * @param mbd the merged bean definition for the bean
 1400   	 * @param args arguments to use if creating a prototype using explicit arguments to a
 1401   	 * static factory method. This parameter must be <code>null</code> except in this case.
 1402   	 * @return a new instance of the bean
 1403   	 * @throws BeanCreationException if the bean could not be created
 1404   	 */
 1405   	protected abstract Object createBean(String beanName, RootBeanDefinition mbd, Object[] args)
 1406   			throws BeanCreationException;
 1407   
 1408   }

Save This Page
Home » spring-framework-2.5.5-with-dependencies » org.springframework » beans » factory » support » [javadoc | source]