Home » Spring-Framework-090522 » org.springframework » beans » factory » [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;
   18   
   19   import java.util.ArrayList;
   20   import java.util.Arrays;
   21   import java.util.Iterator;
   22   import java.util.LinkedHashMap;
   23   import java.util.List;
   24   import java.util.Map;
   25   
   26   import org.springframework.beans.BeansException;
   27   import org.springframework.util.Assert;
   28   import org.springframework.util.StringUtils;
   29   
   30   /**
   31    * Convenience methods operating on bean factories, in particular
   32    * on the {@link ListableBeanFactory} interface.
   33    *
   34    * <p>Returns bean counts, bean names or bean instances,
   35    * taking into account the nesting hierarchy of a bean factory
   36    * (which the methods defined on the ListableBeanFactory interface don't,
   37    * in contrast to the methods defined on the BeanFactory interface).
   38    *
   39    * @author Rod Johnson
   40    * @author Juergen Hoeller
   41    * @since 04.07.2003
   42    */
   43   public abstract class BeanFactoryUtils {
   44   
   45   	/**
   46   	 * Separator for generated bean names. If a class name or parent name is not
   47   	 * unique, "#1", "#2" etc will be appended, until the name becomes unique.
   48   	 */
   49   	public static final String GENERATED_BEAN_NAME_SEPARATOR = "#";
   50   
   51   
   52   	/**
   53   	 * Return whether the given name is a factory dereference
   54   	 * (beginning with the factory dereference prefix).
   55   	 * @param name the name of the bean
   56   	 * @return whether the given name is a factory dereference
   57   	 * @see BeanFactory#FACTORY_BEAN_PREFIX
   58   	 */
   59   	public static boolean isFactoryDereference(String name) {
   60   		return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
   61   	}
   62   
   63   	/**
   64   	 * Return the actual bean name, stripping out the factory dereference
   65   	 * prefix (if any, also stripping repeated factory prefixes if found).
   66   	 * @param name the name of the bean
   67   	 * @return the transformed name
   68   	 * @see BeanFactory#FACTORY_BEAN_PREFIX
   69   	 */
   70   	public static String transformedBeanName(String name) {
   71   		Assert.notNull(name, "'name' must not be null");
   72   		String beanName = name;
   73   		while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
   74   			beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
   75   		}
   76   		return beanName;
   77   	}
   78   
   79   	/**
   80   	 * Return whether the given name is a bean name which has been generated
   81   	 * by the default naming strategy (containing a "#..." part).
   82   	 * @param name the name of the bean
   83   	 * @return whether the given name is a generated bean name
   84   	 * @see #GENERATED_BEAN_NAME_SEPARATOR
   85   	 * @see org.springframework.beans.factory.support.BeanDefinitionReaderUtils#generateBeanName
   86   	 * @see org.springframework.beans.factory.support.DefaultBeanNameGenerator
   87   	 */
   88   	public static boolean isGeneratedBeanName(String name) {
   89   		return (name != null && name.indexOf(GENERATED_BEAN_NAME_SEPARATOR) != -1);
   90   	}
   91   
   92   	/**
   93   	 * Extract the "raw" bean name from the given (potentially generated) bean name,
   94   	 * excluding any "#..." suffixes which might have been added for uniqueness.
   95   	 * @param name the potentially generated bean name
   96   	 * @return the raw bean name
   97   	 * @see #GENERATED_BEAN_NAME_SEPARATOR
   98   	 */
   99   	public static String originalBeanName(String name) {
  100   		Assert.notNull(name, "'name' must not be null");
  101   		int separatorIndex = name.indexOf(GENERATED_BEAN_NAME_SEPARATOR);
  102   		return (separatorIndex != -1 ? name.substring(0, separatorIndex) : name);
  103   	}
  104   
  105   
  106   	/**
  107   	 * Count all beans in any hierarchy in which this factory participates.
  108   	 * Includes counts of ancestor bean factories.
  109   	 * <p>Beans that are "overridden" (specified in a descendant factory
  110   	 * with the same name) are only counted once.
  111   	 * @param lbf the bean factory
  112   	 * @return count of beans including those defined in ancestor factories
  113   	 */
  114   	public static int countBeansIncludingAncestors(ListableBeanFactory lbf) {
  115   		return beanNamesIncludingAncestors(lbf).length;
  116   	}
  117   	
  118   	/**
  119   	 * Return all bean names in the factory, including ancestor factories.
  120   	 * @param lbf the bean factory
  121   	 * @return the array of matching bean names, or an empty array if none
  122   	 * @see #beanNamesForTypeIncludingAncestors
  123   	 */
  124   	public static String[] beanNamesIncludingAncestors(ListableBeanFactory lbf) {
  125   		return beanNamesForTypeIncludingAncestors(lbf, Object.class);
  126   	}
  127   
  128   
  129   	/**
  130   	 * Get all bean names for the given type, including those defined in ancestor
  131   	 * factories. Will return unique names in case of overridden bean definitions.
  132   	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
  133   	 * will get initialized. If the object created by the FactoryBean doesn't match,
  134   	 * the raw FactoryBean itself will be matched against the type.
  135   	 * <p>This version of <code>beanNamesForTypeIncludingAncestors</code> automatically
  136   	 * includes prototypes and FactoryBeans.
  137   	 * @param lbf the bean factory
  138   	 * @param type the type that beans must match
  139   	 * @return the array of matching bean names, or an empty array if none
  140   	 */
  141   	public static String[] beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class type) {
  142   		Assert.notNull(lbf, "ListableBeanFactory must not be null");
  143   		String[] result = lbf.getBeanNamesForType(type);
  144   		if (lbf instanceof HierarchicalBeanFactory) {
  145   			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
  146   			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
  147   				String[] parentResult = beanNamesForTypeIncludingAncestors(
  148   						(ListableBeanFactory) hbf.getParentBeanFactory(), type);
  149   				List resultList = new ArrayList();
  150   				resultList.addAll(Arrays.asList(result));
  151   				for (int i = 0; i < parentResult.length; i++) {
  152   					String beanName = parentResult[i];
  153   					if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
  154   						resultList.add(beanName);
  155   					}
  156   				}
  157   				result = StringUtils.toStringArray(resultList);
  158   			}
  159   		}
  160   		return result;
  161   	}
  162   
  163   	/**
  164   	 * Get all bean names for the given type, including those defined in ancestor
  165   	 * factories. Will return unique names in case of overridden bean definitions.
  166   	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
  167   	 * flag is set, which means that FactoryBeans will get initialized. If the
  168   	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
  169   	 * will be matched against the type. If "allowEagerInit" is not set,
  170   	 * only raw FactoryBeans will be checked (which doesn't require initialization
  171   	 * of each FactoryBean).
  172   	 * @param lbf the bean factory
  173   	 * @param includeNonSingletons whether to include prototype or scoped beans too
  174   	 * or just singletons (also applies to FactoryBeans)
  175   	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
  176   	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
  177   	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
  178   	 * eagerly initialized to determine their type: So be aware that passing in "true"
  179   	 * for this flag will initialize FactoryBeans and "factory-bean" references.
  180   	 * @param type the type that beans must match
  181   	 * @return the array of matching bean names, or an empty array if none
  182   	 */
  183   	public static String[] beanNamesForTypeIncludingAncestors(
  184   			ListableBeanFactory lbf, Class type, boolean includeNonSingletons, boolean allowEagerInit) {
  185   
  186   		Assert.notNull(lbf, "ListableBeanFactory must not be null");
  187   		String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
  188   		if (lbf instanceof HierarchicalBeanFactory) {
  189   			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
  190   			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
  191   				String[] parentResult = beanNamesForTypeIncludingAncestors(
  192   						(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
  193   				List resultList = new ArrayList();
  194   				resultList.addAll(Arrays.asList(result));
  195   				for (int i = 0; i < parentResult.length; i++) {
  196   					String beanName = parentResult[i];
  197   					if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
  198   						resultList.add(beanName);
  199   					}
  200   				}
  201   				result = StringUtils.toStringArray(resultList);
  202   			}
  203   		}
  204   		return result;
  205   	}
  206   
  207   	/**
  208   	 * Return all beans of the given type or subtypes, also picking up beans defined in
  209   	 * ancestor bean factories if the current bean factory is a HierarchicalBeanFactory.
  210   	 * The returned Map will only contain beans of this type.
  211   	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
  212   	 * will get initialized. If the object created by the FactoryBean doesn't match,
  213   	 * the raw FactoryBean itself will be matched against the type.
  214   	 * @param lbf the bean factory
  215   	 * @param type type of bean to match
  216   	 * @return the Map of matching bean instances, or an empty Map if none
  217   	 * @throws BeansException if a bean could not be created
  218   	 */
  219   	public static Map beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class type)
  220   	    throws BeansException {
  221   
  222   		Assert.notNull(lbf, "ListableBeanFactory must not be null");
  223   		Map result = new LinkedHashMap(4);
  224   		result.putAll(lbf.getBeansOfType(type));
  225   		if (lbf instanceof HierarchicalBeanFactory) {
  226   			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
  227   			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
  228   				Map parentResult = beansOfTypeIncludingAncestors(
  229   						(ListableBeanFactory) hbf.getParentBeanFactory(), type);
  230   				for (Iterator it = parentResult.entrySet().iterator(); it.hasNext();) {
  231   					Map.Entry entry = (Map.Entry) it.next();
  232   					String beanName = (String) entry.getKey();
  233   					if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
  234   						result.put(beanName, entry.getValue());
  235   					}
  236   				}
  237   			}
  238   		}
  239   		return result;
  240   	}
  241   
  242   	/**
  243   	 * Return all beans of the given type or subtypes, also picking up beans defined in
  244   	 * ancestor bean factories if the current bean factory is a HierarchicalBeanFactory.
  245   	 * The returned Map will only contain beans of this type.
  246   	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
  247   	 * flag is set, which means that FactoryBeans will get initialized. If the
  248   	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
  249   	 * will be matched against the type. If "allowEagerInit" is not set,
  250   	 * only raw FactoryBeans will be checked (which doesn't require initialization
  251   	 * of each FactoryBean).
  252   	 * @param lbf the bean factory
  253   	 * @param type type of bean to match
  254   	 * @param includeNonSingletons whether to include prototype or scoped beans too
  255   	 * or just singletons (also applies to FactoryBeans)
  256   	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
  257   	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
  258   	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
  259   	 * eagerly initialized to determine their type: So be aware that passing in "true"
  260   	 * for this flag will initialize FactoryBeans and "factory-bean" references.
  261   	 * @return the Map of matching bean instances, or an empty Map if none
  262   	 * @throws BeansException if a bean could not be created
  263   	 */
  264   	public static Map beansOfTypeIncludingAncestors(
  265   			ListableBeanFactory lbf, Class type, boolean includeNonSingletons, boolean allowEagerInit)
  266   	    throws BeansException {
  267   
  268   		Assert.notNull(lbf, "ListableBeanFactory must not be null");
  269   		Map result = new LinkedHashMap(4);
  270   		result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));
  271   		if (lbf instanceof HierarchicalBeanFactory) {
  272   			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
  273   			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
  274   				Map parentResult = beansOfTypeIncludingAncestors(
  275   						(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
  276   				for (Iterator it = parentResult.entrySet().iterator(); it.hasNext();) {
  277   					Map.Entry entry = (Map.Entry) it.next();
  278   					String beanName = (String) entry.getKey();
  279   					if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
  280   						result.put(beanName, entry.getValue());
  281   					}
  282   				}
  283   			}
  284   		}
  285   		return result;
  286   	}
  287   
  288   
  289   	/**
  290   	 * Return a single bean of the given type or subtypes, also picking up beans
  291   	 * defined in ancestor bean factories if the current bean factory is a
  292   	 * HierarchicalBeanFactory. Useful convenience method when we expect a
  293   	 * single bean and don't care about the bean name.
  294   	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
  295   	 * will get initialized. If the object created by the FactoryBean doesn't match,
  296   	 * the raw FactoryBean itself will be matched against the type.
  297   	 * <p>This version of <code>beanOfTypeIncludingAncestors</code> automatically includes
  298   	 * prototypes and FactoryBeans.
  299   	 * @param lbf the bean factory
  300   	 * @param type type of bean to match
  301   	 * @return the matching bean instance
  302   	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
  303   	 * if 0 or more than 1 beans of the given type were found
  304   	 * @throws BeansException if the bean could not be created
  305   	 */
  306   	public static Object beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class type)
  307   			throws BeansException {
  308   
  309   		Map beansOfType = beansOfTypeIncludingAncestors(lbf, type);
  310   		if (beansOfType.size() == 1) {
  311   			return beansOfType.values().iterator().next();
  312   		}
  313   		else {
  314   			throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
  315   		}
  316   	}
  317   
  318   	/**
  319   	 * Return a single bean of the given type or subtypes, also picking up beans
  320   	 * defined in ancestor bean factories if the current bean factory is a
  321   	 * HierarchicalBeanFactory. Useful convenience method when we expect a
  322   	 * single bean and don't care about the bean name.
  323   	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
  324   	 * flag is set, which means that FactoryBeans will get initialized. If the
  325   	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
  326   	 * will be matched against the type. If "allowEagerInit" is not set,
  327   	 * only raw FactoryBeans will be checked (which doesn't require initialization
  328   	 * of each FactoryBean).
  329   	 * @param lbf the bean factory
  330   	 * @param type type of bean to match
  331   	 * @param includeNonSingletons whether to include prototype or scoped beans too
  332   	 * or just singletons (also applies to FactoryBeans)
  333   	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
  334   	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
  335   	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
  336   	 * eagerly initialized to determine their type: So be aware that passing in "true"
  337   	 * for this flag will initialize FactoryBeans and "factory-bean" references.
  338   	 * @return the matching bean instance
  339   	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
  340   	 * if 0 or more than 1 beans of the given type were found
  341   	 * @throws BeansException if the bean could not be created
  342   	 */
  343   	public static Object beanOfTypeIncludingAncestors(
  344   			ListableBeanFactory lbf, Class type, boolean includeNonSingletons, boolean allowEagerInit)
  345   	    throws BeansException {
  346   
  347   		Map beansOfType = beansOfTypeIncludingAncestors(lbf, type, includeNonSingletons, allowEagerInit);
  348   		if (beansOfType.size() == 1) {
  349   			return beansOfType.values().iterator().next();
  350   		}
  351   		else {
  352   			throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
  353   		}
  354   	}
  355   
  356   	/**
  357   	 * Return a single bean of the given type or subtypes, not looking in ancestor
  358   	 * factories. Useful convenience method when we expect a single bean and
  359   	 * don't care about the bean name.
  360   	 * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
  361   	 * will get initialized. If the object created by the FactoryBean doesn't match,
  362   	 * the raw FactoryBean itself will be matched against the type.
  363   	 * <p>This version of <code>beanOfType</code> automatically includes
  364   	 * prototypes and FactoryBeans.
  365   	 * @param lbf the bean factory
  366   	 * @param type type of bean to match
  367   	 * @return the matching bean instance
  368   	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
  369   	 * if 0 or more than 1 beans of the given type were found
  370   	 * @throws BeansException if the bean could not be created
  371   	 */
  372   	public static Object beanOfType(ListableBeanFactory lbf, Class type) throws BeansException {
  373   		Assert.notNull(lbf, "ListableBeanFactory must not be null");
  374   		Map beansOfType = lbf.getBeansOfType(type);
  375   		if (beansOfType.size() == 1) {
  376   			return beansOfType.values().iterator().next();
  377   		}
  378   		else {
  379   			throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
  380   		}
  381   	}
  382   
  383   	/**
  384   	 * Return a single bean of the given type or subtypes, not looking in ancestor
  385   	 * factories. Useful convenience method when we expect a single bean and
  386   	 * don't care about the bean name.
  387   	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
  388   	 * flag is set, which means that FactoryBeans will get initialized. If the
  389   	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
  390   	 * will be matched against the type. If "allowEagerInit" is not set,
  391   	 * only raw FactoryBeans will be checked (which doesn't require initialization
  392   	 * of each FactoryBean).
  393   	 * @param lbf the bean factory
  394   	 * @param type type of bean to match
  395   	 * @param includeNonSingletons whether to include prototype or scoped beans too
  396   	 * or just singletons (also applies to FactoryBeans)
  397   	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
  398   	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
  399   	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
  400   	 * eagerly initialized to determine their type: So be aware that passing in "true"
  401   	 * for this flag will initialize FactoryBeans and "factory-bean" references.
  402   	 * @return the matching bean instance
  403   	 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
  404   	 * if 0 or more than 1 beans of the given type were found
  405   	 * @throws BeansException if the bean could not be created
  406   	 */
  407   	public static Object beanOfType(
  408   			ListableBeanFactory lbf, Class type, boolean includeNonSingletons, boolean allowEagerInit)
  409   	    throws BeansException {
  410   
  411   		Assert.notNull(lbf, "ListableBeanFactory must not be null");
  412   		Map beansOfType = lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit);
  413   		if (beansOfType.size() == 1) {
  414   			return beansOfType.values().iterator().next();
  415   		}
  416   		else {
  417   			throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
  418   		}
  419   	}
  420   
  421   }

Home » Spring-Framework-090522 » org.springframework » beans » factory » [javadoc | source]