public void preInstantiateSingletons() throws BeansException {
   if (logger.isInfoEnabled()) {
     logger.info("Pre-instantiating singletons in factory [" + this + "]");
   }
   try {
     for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext(); ) {
       String beanName = (String) it.next();
       if (containsBeanDefinition(beanName)) {
         RootBeanDefinition bd = getMergedBeanDefinition(beanName, false);
         if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
           if (bd.hasBeanClass() && FactoryBean.class.isAssignableFrom(bd.getBeanClass())) {
             FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
             if (factory.isSingleton()) {
               getBean(beanName);
             }
           } else {
             getBean(beanName);
           }
         }
       }
     }
   } catch (BeansException ex) {
     // destroy already created singletons to avoid dangling resources
     try {
       destroySingletons();
     } catch (Throwable ex2) {
       logger.error(
           "Pre-instantiating singletons failed, "
               + "and couldn't destroy already created singletons",
           ex2);
     }
     throw ex;
   }
 }
 /**
  * Determine whether the bean definition with the given name matches the given type.
  *
  * @param beanName the name of the bean to check
  * @param type class or interface to match, or <code>null</code> for all bean names
  * @return whether the type matches
  * @see RootBeanDefinition#hasBeanClass
  * @see RootBeanDefinition#getBeanClass
  */
 private boolean isBeanDefinitionTypeMatch(String beanName, Class type) {
   if (type == null) {
     return true;
   }
   RootBeanDefinition rbd = getMergedBeanDefinition(beanName, false);
   return (rbd.hasBeanClass() && type.isAssignableFrom(rbd.getBeanClass()));
 }
  public String[] getBeanNamesForType(
      Class type, boolean includePrototypes, boolean includeFactoryBeans) {
    List result = new ArrayList();

    // Check all bean definitions.
    for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext(); ) {
      String beanName = (String) it.next();
      RootBeanDefinition rbd = getMergedBeanDefinition(beanName, false);
      // Only check bean definition if it is complete.
      if (!rbd.isAbstract()) {
        // In case of FactoryBean, match object created by FactoryBean.
        boolean isFactoryBean =
            rbd.hasBeanClass() && FactoryBean.class.isAssignableFrom(rbd.getBeanClass());
        if (isFactoryBean || rbd.getFactoryBeanName() != null) {
          if (includeFactoryBeans
              && (includePrototypes || isSingleton(beanName))
              && isBeanTypeMatch(beanName, type)) {
            result.add(beanName);
            // Match found for this bean: do not match FactoryBean itself anymore.
            continue;
          }
          // We're done for anything but a full FactoryBean.
          if (!isFactoryBean) {
            continue;
          }
          // In case of FactoryBean, try to match FactoryBean itself next.
          beanName = FACTORY_BEAN_PREFIX + beanName;
        }
        // Match raw bean instance (might be raw FactoryBean).
        if ((includePrototypes || rbd.isSingleton()) && isBeanTypeMatch(beanName, type)) {
          result.add(beanName);
        }
      }
    }

    // Check singletons too, to catch manually registered singletons.
    String[] singletonNames = getSingletonNames();
    for (int i = 0; i < singletonNames.length; i++) {
      String beanName = singletonNames[i];
      // Only check if manually registered.
      if (!containsBeanDefinition(beanName)) {
        // In case of FactoryBean, match object created by FactoryBean.
        if (isFactoryBean(beanName)) {
          if (includeFactoryBeans
              && (includePrototypes || isSingleton(beanName))
              && isBeanTypeMatch(beanName, type)) {
            result.add(beanName);
            // Match found for this bean: do not match FactoryBean itself anymore.
            continue;
          }
          // In case of FactoryBean, try to match FactoryBean itself next.
          beanName = FACTORY_BEAN_PREFIX + beanName;
        }
        // Match raw bean instance (might be raw FactoryBean).
        if (isBeanTypeMatch(beanName, type)) {
          result.add(beanName);
        }
      }
    }

    return (String[]) result.toArray(new String[result.size()]);
  }
  /**
   * Instantiate the bean using a named factory method. The method may be static, if the bean
   * definition parameter specifies a class, rather than a "factory-bean", or an instance variable
   * on a factory object itself configured using Dependency Injection.
   *
   * <p>Implementation requires iterating over the static or instance methods with the name
   * specified in the RootBeanDefinition (the method may be overloaded) and trying to match with the
   * parameters. We don't have the types attached to constructor args, so trial and error is the
   * only way to go here. The explicitArgs array may contain argument values passed in
   * programmatically via the corresponding getBean method.
   *
   * @param beanName the name of the bean
   * @param mbd the merged bean definition for the bean
   * @param explicitArgs argument values passed in programmatically via the getBean method, or
   *     {@code null} if none (-> use constructor argument values from bean definition)
   * @return a BeanWrapper for the new instance
   */
  public BeanWrapper instantiateUsingFactoryMethod(
      final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {

    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);

    Object factoryBean;
    Class<?> factoryClass;
    boolean isStatic;

    String factoryBeanName = mbd.getFactoryBeanName();
    if (factoryBeanName != null) {
      if (factoryBeanName.equals(beanName)) {
        throw new BeanDefinitionStoreException(
            mbd.getResourceDescription(),
            beanName,
            "factory-bean reference points back to the same bean definition");
      }
      factoryBean = this.beanFactory.getBean(factoryBeanName);
      if (factoryBean == null) {
        throw new BeanCreationException(
            mbd.getResourceDescription(),
            beanName,
            "factory-bean '"
                + factoryBeanName
                + "' (or a BeanPostProcessor involved) returned null");
      }
      if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
        throw new IllegalStateException(
            "About-to-be-created singleton instance implicitly appeared "
                + "through the creation of the factory bean that its bean definition points to");
      }
      factoryClass = factoryBean.getClass();
      isStatic = false;
    } else {
      // It's a static factory method on the bean class.
      if (!mbd.hasBeanClass()) {
        throw new BeanDefinitionStoreException(
            mbd.getResourceDescription(),
            beanName,
            "bean definition declares neither a bean class nor a factory-bean reference");
      }
      factoryBean = null;
      factoryClass = mbd.getBeanClass();
      isStatic = true;
    }

    Method factoryMethodToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;

    if (explicitArgs != null) {
      argsToUse = explicitArgs;
    } else {
      Object[] argsToResolve = null;
      synchronized (mbd.constructorArgumentLock) {
        factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
        if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
          // Found a cached factory method...
          argsToUse = mbd.resolvedConstructorArguments;
          if (argsToUse == null) {
            argsToResolve = mbd.preparedConstructorArguments;
          }
        }
      }
      if (argsToResolve != null) {
        argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
      }
    }

    if (factoryMethodToUse == null || argsToUse == null) {
      // Need to determine the factory method...
      // Try all methods with this name to see if they match the given arguments.
      factoryClass = ClassUtils.getUserClass(factoryClass);

      Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
      List<Method> candidateSet = new ArrayList<Method>();
      for (Method candidate : rawCandidates) {
        if (Modifier.isStatic(candidate.getModifiers()) == isStatic
            && mbd.isFactoryMethod(candidate)) {
          candidateSet.add(candidate);
        }
      }
      Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
      AutowireUtils.sortFactoryMethods(candidates);

      ConstructorArgumentValues resolvedValues = null;
      boolean autowiring =
          (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
      int minTypeDiffWeight = Integer.MAX_VALUE;
      Set<Method> ambiguousFactoryMethods = null;

      int minNrOfArgs;
      if (explicitArgs != null) {
        minNrOfArgs = explicitArgs.length;
      } else {
        // We don't have arguments passed in programmatically, so we need to resolve the
        // arguments specified in the constructor arguments held in the bean definition.
        ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
        resolvedValues = new ConstructorArgumentValues();
        minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
      }

      List<Exception> causes = null;

      for (int i = 0; i < candidates.length; i++) {
        Method candidate = candidates[i];
        Class<?>[] paramTypes = candidate.getParameterTypes();

        if (paramTypes.length >= minNrOfArgs) {
          ArgumentsHolder argsHolder;

          if (resolvedValues != null) {
            // Resolved constructor arguments: type conversion and/or autowiring necessary.
            try {
              String[] paramNames = null;
              ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
              if (pnd != null) {
                paramNames = pnd.getParameterNames(candidate);
              }
              argsHolder =
                  createArgumentArray(
                      beanName,
                      mbd,
                      resolvedValues,
                      bw,
                      paramTypes,
                      paramNames,
                      candidate,
                      autowiring);
            } catch (UnsatisfiedDependencyException ex) {
              if (this.beanFactory.logger.isTraceEnabled()) {
                this.beanFactory.logger.trace(
                    "Ignoring factory method ["
                        + candidate
                        + "] of bean '"
                        + beanName
                        + "': "
                        + ex);
              }
              if (i == candidates.length - 1 && argsHolderToUse == null) {
                if (causes != null) {
                  for (Exception cause : causes) {
                    this.beanFactory.onSuppressedException(cause);
                  }
                }
                throw ex;
              } else {
                // Swallow and try next overloaded factory method.
                if (causes == null) {
                  causes = new LinkedList<Exception>();
                }
                causes.add(ex);
                continue;
              }
            }
          } else {
            // Explicit arguments given -> arguments length must match exactly.
            if (paramTypes.length != explicitArgs.length) {
              continue;
            }
            argsHolder = new ArgumentsHolder(explicitArgs);
          }

          int typeDiffWeight =
              (mbd.isLenientConstructorResolution()
                  ? argsHolder.getTypeDifferenceWeight(paramTypes)
                  : argsHolder.getAssignabilityWeight(paramTypes));
          // Choose this factory method if it represents the closest match.
          if (typeDiffWeight < minTypeDiffWeight) {
            factoryMethodToUse = candidate;
            argsHolderToUse = argsHolder;
            argsToUse = argsHolder.arguments;
            minTypeDiffWeight = typeDiffWeight;
            ambiguousFactoryMethods = null;
          }
          // Find out about ambiguity: In case of the same type difference weight
          // for methods with the same number of parameters, collect such candidates
          // and eventually raise an ambiguity exception.
          // However, only perform that check in non-lenient constructor resolution mode,
          // and explicitly ignore overridden methods (with the same parameter signature).
          else if (factoryMethodToUse != null
              && typeDiffWeight == minTypeDiffWeight
              && !mbd.isLenientConstructorResolution()
              && paramTypes.length == factoryMethodToUse.getParameterTypes().length
              && !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
            if (ambiguousFactoryMethods == null) {
              ambiguousFactoryMethods = new LinkedHashSet<Method>();
              ambiguousFactoryMethods.add(factoryMethodToUse);
            }
            ambiguousFactoryMethods.add(candidate);
          }
        }
      }

      if (factoryMethodToUse == null) {
        List<String> argTypes = new ArrayList<String>(minNrOfArgs);
        if (explicitArgs != null) {
          for (Object arg : explicitArgs) {
            argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
          }
        } else {
          Set<ValueHolder> valueHolders =
              new LinkedHashSet<ValueHolder>(resolvedValues.getArgumentCount());
          valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
          valueHolders.addAll(resolvedValues.getGenericArgumentValues());
          for (ValueHolder value : valueHolders) {
            String argType =
                (value.getType() != null
                    ? ClassUtils.getShortName(value.getType())
                    : (value.getValue() != null
                        ? value.getValue().getClass().getSimpleName()
                        : "null"));
            argTypes.add(argType);
          }
        }
        String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
        throw new BeanCreationException(
            mbd.getResourceDescription(),
            beanName,
            "No matching factory method found: "
                + (mbd.getFactoryBeanName() != null
                    ? "factory bean '" + mbd.getFactoryBeanName() + "'; "
                    : "")
                + "factory method '"
                + mbd.getFactoryMethodName()
                + "("
                + argDesc
                + ")'. "
                + "Check that a method with the specified name "
                + (minNrOfArgs > 0 ? "and arguments " : "")
                + "exists and that it is "
                + (isStatic ? "static" : "non-static")
                + ".");
      } else if (void.class.equals(factoryMethodToUse.getReturnType())) {
        throw new BeanCreationException(
            mbd.getResourceDescription(),
            beanName,
            "Invalid factory method '"
                + mbd.getFactoryMethodName()
                + "': needs to have a non-void return type!");
      } else if (ambiguousFactoryMethods != null) {
        throw new BeanCreationException(
            mbd.getResourceDescription(),
            beanName,
            "Ambiguous factory method matches found in bean '"
                + beanName
                + "' "
                + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): "
                + ambiguousFactoryMethods);
      }

      if (explicitArgs == null && argsHolderToUse != null) {
        argsHolderToUse.storeCache(mbd, factoryMethodToUse);
      }
    }

    try {
      Object beanInstance;

      if (System.getSecurityManager() != null) {
        final Object fb = factoryBean;
        final Method factoryMethod = factoryMethodToUse;
        final Object[] args = argsToUse;
        beanInstance =
            AccessController.doPrivileged(
                new PrivilegedAction<Object>() {
                  @Override
                  public Object run() {
                    return beanFactory
                        .getInstantiationStrategy()
                        .instantiate(mbd, beanName, beanFactory, fb, factoryMethod, args);
                  }
                },
                beanFactory.getAccessControlContext());
      } else {
        beanInstance =
            this.beanFactory
                .getInstantiationStrategy()
                .instantiate(
                    mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
      }

      if (beanInstance == null) {
        return null;
      }
      bw.setWrappedInstance(beanInstance);
      return bw;
    } catch (Throwable ex) {
      throw new BeanCreationException(
          mbd.getResourceDescription(),
          beanName,
          "Bean instantiation via factory method failed",
          ex);
    }
  }