@Test
 public void
     testAutowiredFieldDoesNotResolveWithMultipleQualifierValuesAndMultipleMatchingCandidates() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   AutowireCandidateQualifier qualifier =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier.setAttribute("number", 123);
   person1.addQualifier(qualifier);
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   AutowireCandidateQualifier qualifier2 =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier2.setAttribute("number", 123);
   qualifier2.setAttribute("value", "default");
   person2.addQualifier(qualifier2);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
     assertEquals("autowired", e.getBeanName());
   }
 }
 @Test
 public void
     testAutowiredFieldDoesNotResolveWithBaseQualifierAndNonDefaultValueAndMultipleMatchingCandidates() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue("the real juergen");
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   person1.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "juergen"));
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue("juergen imposter");
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   person2.addQualifier(new AutowireCandidateQualifier(Qualifier.class, "juergen"));
   context.registerBeanDefinition("juergen1", person1);
   context.registerBeanDefinition("juergen2", person2);
   context.registerBeanDefinition(
       "autowired",
       new RootBeanDefinition(
           QualifiedConstructorArgumentWithBaseQualifierNonDefaultValueTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e instanceof UnsatisfiedDependencyException);
     assertEquals("autowired", e.getBeanName());
   }
 }
 @Test
 public void testAutowiredFieldResolvesWithMultipleQualifierValuesAndExplicitDefaultValue() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   AutowireCandidateQualifier qualifier =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier.setAttribute("number", 456);
   person1.addQualifier(qualifier);
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   AutowireCandidateQualifier qualifier2 =
       new AutowireCandidateQualifier(TestQualifierWithMultipleAttributes.class);
   qualifier2.setAttribute("number", 123);
   qualifier2.setAttribute("value", "default");
   person2.addQualifier(qualifier2);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithMultipleAttributesTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedFieldWithMultipleAttributesTestBean bean =
       (QualifiedFieldWithMultipleAttributesTestBean) context.getBean("autowired");
   assertEquals(MARK, bean.getPerson().getName());
 }
 /**
  * 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()));
 }
 @Test
 public void
     testAutowiredFieldDoesNotResolveCandidateWithDefaultValueAndConflictingValueOnBeanDefinition() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   // qualifier added, and non-default value specified
   person1.addQualifier(
       new AutowireCandidateQualifier(TestQualifierWithDefaultValue.class, "not the default"));
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithDefaultValueTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   try {
     context.refresh();
     fail("expected BeanCreationException");
   } catch (BeanCreationException e) {
     assertTrue(e.getRootCause() instanceof NoSuchBeanDefinitionException);
     assertEquals("autowired", e.getBeanName());
   }
 }
  /**
   * Resolve the factory method in the specified bean definition, if possible. {@link
   * RootBeanDefinition#getResolvedFactoryMethod()} can be checked for the result.
   *
   * @param mbd the bean definition to check
   */
  public void resolveFactoryMethodIfPossible(RootBeanDefinition mbd) {
    Class<?> factoryClass;
    boolean isStatic;
    if (mbd.getFactoryBeanName() != null) {
      factoryClass = this.beanFactory.getType(mbd.getFactoryBeanName());
      isStatic = false;
    } else {
      factoryClass = mbd.getBeanClass();
      isStatic = true;
    }
    factoryClass = ClassUtils.getUserClass(factoryClass);

    Method[] candidates = getCandidateMethods(factoryClass, mbd);
    Method uniqueCandidate = null;
    for (Method candidate : candidates) {
      if (Modifier.isStatic(candidate.getModifiers()) == isStatic
          && mbd.isFactoryMethod(candidate)) {
        if (uniqueCandidate == null) {
          uniqueCandidate = candidate;
        } else if (!Arrays.equals(
            uniqueCandidate.getParameterTypes(), candidate.getParameterTypes())) {
          uniqueCandidate = null;
          break;
        }
      }
    }
    synchronized (mbd.constructorArgumentLock) {
      mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
    }
  }
 public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) {
   synchronized (mbd.constructorArgumentLock) {
     mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
     mbd.constructorArgumentsResolved = true;
     if (this.resolveNecessary) {
       mbd.preparedConstructorArguments = this.preparedArguments;
     } else {
       mbd.resolvedConstructorArguments = this.arguments;
     }
   }
 }
 @Test
 public void testAutowiredFieldWithSingleQualifiedCandidate() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs = new ConstructorArgumentValues();
   cavs.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person = new RootBeanDefinition(Person.class, cavs, null);
   person.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
   context.registerBeanDefinition(JUERGEN, person);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedFieldTestBean bean = (QualifiedFieldTestBean) context.getBean("autowired");
   assertEquals(JUERGEN, bean.getPerson().getName());
 }
  /**
   * Resolve the constructor arguments for this bean into the resolvedValues object. This may
   * involve looking up other beans.
   *
   * <p>This method is also used for handling invocations of static factory methods.
   */
  private int resolveConstructorArguments(
      String beanName,
      RootBeanDefinition mbd,
      BeanWrapper bw,
      ConstructorArgumentValues cargs,
      ConstructorArgumentValues resolvedValues) {

    TypeConverter converter =
        (this.beanFactory.getCustomTypeConverter() != null
            ? this.beanFactory.getCustomTypeConverter()
            : bw);
    BeanDefinitionValueResolver valueResolver =
        new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);

    int minNrOfArgs = cargs.getArgumentCount();

    for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry :
        cargs.getIndexedArgumentValues().entrySet()) {
      int index = entry.getKey();
      if (index < 0) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid constructor argument index: " + index);
      }
      if (index > minNrOfArgs) {
        minNrOfArgs = index + 1;
      }
      ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
      if (valueHolder.isConverted()) {
        resolvedValues.addIndexedArgumentValue(index, valueHolder);
      } else {
        Object resolvedValue =
            valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
        ConstructorArgumentValues.ValueHolder resolvedValueHolder =
            new ConstructorArgumentValues.ValueHolder(
                resolvedValue, valueHolder.getType(), valueHolder.getName());
        resolvedValueHolder.setSource(valueHolder);
        resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
      }
    }

    for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
      if (valueHolder.isConverted()) {
        resolvedValues.addGenericArgumentValue(valueHolder);
      } else {
        Object resolvedValue =
            valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
        ConstructorArgumentValues.ValueHolder resolvedValueHolder =
            new ConstructorArgumentValues.ValueHolder(
                resolvedValue, valueHolder.getType(), valueHolder.getName());
        resolvedValueHolder.setSource(valueHolder);
        resolvedValues.addGenericArgumentValue(resolvedValueHolder);
      }
    }

    return minNrOfArgs;
  }
 @Test
 public void testAutowiredMethodParameterResolvesQualifiedCandidate() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   person1.addQualifier(new AutowireCandidateQualifier(TestQualifier.class));
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedMethodParameterTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedMethodParameterTestBean bean =
       (QualifiedMethodParameterTestBean) context.getBean("autowired");
   assertEquals(JUERGEN, bean.getPerson().getName());
 }
 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;
   }
 }
  /** Resolve the prepared arguments stored in the given bean definition. */
  private Object[] resolvePreparedArguments(
      String beanName,
      RootBeanDefinition mbd,
      BeanWrapper bw,
      Member methodOrCtor,
      Object[] argsToResolve) {

    Class<?>[] paramTypes =
        (methodOrCtor instanceof Method
            ? ((Method) methodOrCtor).getParameterTypes()
            : ((Constructor<?>) methodOrCtor).getParameterTypes());
    TypeConverter converter =
        (this.beanFactory.getCustomTypeConverter() != null
            ? this.beanFactory.getCustomTypeConverter()
            : bw);
    BeanDefinitionValueResolver valueResolver =
        new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
    Object[] resolvedArgs = new Object[argsToResolve.length];
    for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
      Object argValue = argsToResolve[argIndex];
      MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, argIndex);
      GenericTypeResolver.resolveParameterType(methodParam, methodOrCtor.getDeclaringClass());
      if (argValue instanceof AutowiredArgumentMarker) {
        argValue = resolveAutowiredArgument(methodParam, beanName, null, converter);
      } else if (argValue instanceof BeanMetadataElement) {
        argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
      } else if (argValue instanceof String) {
        argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
      }
      Class<?> paramType = paramTypes[argIndex];
      try {
        resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
      } catch (TypeMismatchException ex) {
        String methodType =
            (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
        throw new UnsatisfiedDependencyException(
            mbd.getResourceDescription(),
            beanName,
            argIndex,
            paramType,
            "Could not convert "
                + methodType
                + " argument value of type ["
                + ObjectUtils.nullSafeClassName(argValue)
                + "] to required type ["
                + paramType.getName()
                + "]: "
                + ex.getMessage());
      }
    }
    return resolvedArgs;
  }
 @Test
 public void testAutowiredFieldResolvesWithDefaultValueAndExplicitDefaultValueOnBeanDefinition() {
   GenericApplicationContext context = new GenericApplicationContext();
   ConstructorArgumentValues cavs1 = new ConstructorArgumentValues();
   cavs1.addGenericArgumentValue(JUERGEN);
   RootBeanDefinition person1 = new RootBeanDefinition(Person.class, cavs1, null);
   // qualifier added, and value matches the default
   person1.addQualifier(
       new AutowireCandidateQualifier(TestQualifierWithDefaultValue.class, "default"));
   ConstructorArgumentValues cavs2 = new ConstructorArgumentValues();
   cavs2.addGenericArgumentValue(MARK);
   RootBeanDefinition person2 = new RootBeanDefinition(Person.class, cavs2, null);
   context.registerBeanDefinition(JUERGEN, person1);
   context.registerBeanDefinition(MARK, person2);
   context.registerBeanDefinition(
       "autowired", new RootBeanDefinition(QualifiedFieldWithDefaultValueTestBean.class));
   AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
   context.refresh();
   QualifiedFieldWithDefaultValueTestBean bean =
       (QualifiedFieldWithDefaultValueTestBean) context.getBean("autowired");
   assertEquals(JUERGEN, bean.getPerson().getName());
 }
 /**
  * Retrieve all candidate methods for the given class, considering the {@link
  * RootBeanDefinition#isNonPublicAccessAllowed()} flag. Called as the starting point for factory
  * method determination.
  */
 private Method[] getCandidateMethods(final Class<?> factoryClass, final RootBeanDefinition mbd) {
   if (System.getSecurityManager() != null) {
     return AccessController.doPrivileged(
         new PrivilegedAction<Method[]>() {
           @Override
           public Method[] run() {
             return (mbd.isNonPublicAccessAllowed()
                 ? ReflectionUtils.getAllDeclaredMethods(factoryClass)
                 : factoryClass.getMethods());
           }
         });
   } else {
     return (mbd.isNonPublicAccessAllowed()
         ? ReflectionUtils.getAllDeclaredMethods(factoryClass)
         : factoryClass.getMethods());
   }
 }
 /**
  * Resolve an inner bean definition.
  *
  * @param argName the name of the argument that the inner bean is defined for
  * @param innerBeanName the name of the inner bean
  * @param innerBd the bean definition for the inner bean
  * @return the resolved inner bean instance
  */
 private Object resolveInnerBean(Object argName, String innerBeanName, BeanDefinition innerBd) {
   RootBeanDefinition mbd = null;
   try {
     mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);
     // Check given bean name whether it is unique. If not already unique,
     // add counter - increasing the counter until the name is unique.
     String actualInnerBeanName = innerBeanName;
     if (mbd.isSingleton()) {
       actualInnerBeanName = adaptInnerBeanName(innerBeanName);
     }
     this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);
     // Guarantee initialization of beans that the inner bean depends on.
     String[] dependsOn = mbd.getDependsOn();
     if (dependsOn != null) {
       for (String dependsOnBean : dependsOn) {
         this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
         this.beanFactory.getBean(dependsOnBean);
       }
     }
     // Actually create the inner bean instance now...
     Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
     if (innerBean instanceof FactoryBean) {
       boolean synthetic = mbd.isSynthetic();
       return this.beanFactory.getObjectFromFactoryBean(
           (FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
     } else {
       return innerBean;
     }
   } catch (BeansException ex) {
     throw new BeanCreationException(
         this.beanDefinition.getResourceDescription(),
         this.beanName,
         "Cannot create inner bean '"
             + innerBeanName
             + "' "
             + (mbd != null && mbd.getBeanClassName() != null
                 ? "of type [" + mbd.getBeanClassName() + "] "
                 : "")
             + "while setting "
             + argName,
         ex);
   }
 }
  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()]);
  }
  /**
   * Create an array of arguments to invoke a constructor or factory method, given the resolved
   * constructor argument values.
   */
  private ArgumentsHolder createArgumentArray(
      String beanName,
      RootBeanDefinition mbd,
      ConstructorArgumentValues resolvedValues,
      BeanWrapper bw,
      Class<?>[] paramTypes,
      String[] paramNames,
      Object methodOrCtor,
      boolean autowiring)
      throws UnsatisfiedDependencyException {

    String methodType = (methodOrCtor instanceof Constructor ? "constructor" : "factory method");
    TypeConverter converter =
        (this.beanFactory.getCustomTypeConverter() != null
            ? this.beanFactory.getCustomTypeConverter()
            : bw);

    ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
    Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
        new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
    Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);

    for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
      Class<?> paramType = paramTypes[paramIndex];
      String paramName = (paramNames != null ? paramNames[paramIndex] : null);
      // Try to find matching constructor argument value, either indexed or generic.
      ConstructorArgumentValues.ValueHolder valueHolder =
          resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
      // If we couldn't find a direct match and are not supposed to autowire,
      // let's try the next generic, untyped argument value as fallback:
      // it could match after type conversion (for example, String -> int).
      if (valueHolder == null && !autowiring) {
        valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
      }
      if (valueHolder != null) {
        // We found a potential match - let's give it a try.
        // Do not consider the same value definition multiple times!
        usedValueHolders.add(valueHolder);
        Object originalValue = valueHolder.getValue();
        Object convertedValue;
        if (valueHolder.isConverted()) {
          convertedValue = valueHolder.getConvertedValue();
          args.preparedArguments[paramIndex] = convertedValue;
        } else {
          ConstructorArgumentValues.ValueHolder sourceHolder =
              (ConstructorArgumentValues.ValueHolder) valueHolder.getSource();
          Object sourceValue = sourceHolder.getValue();
          try {
            convertedValue =
                converter.convertIfNecessary(
                    originalValue,
                    paramType,
                    MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex));
            // TODO re-enable once race condition has been found (SPR-7423)
            /*
            if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {
            	// Either a converted value or still the original one: store converted value.
            	sourceHolder.setConvertedValue(convertedValue);
            	args.preparedArguments[paramIndex] = convertedValue;
            }
            else {
            */
            args.resolveNecessary = true;
            args.preparedArguments[paramIndex] = sourceValue;
            // }
          } catch (TypeMismatchException ex) {
            throw new UnsatisfiedDependencyException(
                mbd.getResourceDescription(),
                beanName,
                paramIndex,
                paramType,
                "Could not convert "
                    + methodType
                    + " argument value of type ["
                    + ObjectUtils.nullSafeClassName(valueHolder.getValue())
                    + "] to required type ["
                    + paramType.getName()
                    + "]: "
                    + ex.getMessage());
          }
        }
        args.arguments[paramIndex] = convertedValue;
        args.rawArguments[paramIndex] = originalValue;
      } else {
        // No explicit match found: we're either supposed to autowire or
        // have to fail creating an argument array for the given constructor.
        if (!autowiring) {
          throw new UnsatisfiedDependencyException(
              mbd.getResourceDescription(),
              beanName,
              paramIndex,
              paramType,
              "Ambiguous "
                  + methodType
                  + " argument types - "
                  + "did you specify the correct bean references as "
                  + methodType
                  + " arguments?");
        }
        try {
          MethodParameter param = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);
          Object autowiredArgument =
              resolveAutowiredArgument(param, beanName, autowiredBeanNames, converter);
          args.rawArguments[paramIndex] = autowiredArgument;
          args.arguments[paramIndex] = autowiredArgument;
          args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
          args.resolveNecessary = true;
        } catch (BeansException ex) {
          throw new UnsatisfiedDependencyException(
              mbd.getResourceDescription(), beanName, paramIndex, paramType, ex);
        }
      }
    }

    for (String autowiredBeanName : autowiredBeanNames) {
      this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
      if (this.beanFactory.logger.isDebugEnabled()) {
        this.beanFactory.logger.debug(
            "Autowiring by type from bean name '"
                + beanName
                + "' via "
                + methodType
                + " to bean named '"
                + autowiredBeanName
                + "'");
      }
    }

    return args;
  }
  /**
   * 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);
    }
  }
  /**
   * 带有参数的实例化Bean方法,主要完成的功能如下: 1. 构造函数参数的确定 1)根据explicitArgs参数判断 2)从缓存中获取 3)从配置文件获取 2. 构造函数的确定 3.
   * 根据确定的构造函数转换对应的参数类型 4. 构造函数不确定性的验证 5. 根据实例化策略以及得到的构造函数和构造函数参数实例化bean
   */
  public BeanWrapper autowireConstructor(
      final String beanName,
      final RootBeanDefinition mbd,
      Constructor<?>[] chosenCtors,
      final Object[] explicitArgs) {

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

    // 定义选取的构造函数
    Constructor<?> constructorToUse = null;
    // 定义选取的构造函数参数
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;

    // 如果getBean调用时指定了方法参数,则直接使用
    if (explicitArgs != null) {
      argsToUse = explicitArgs;
    }
    // getBean方法未指定参数,则从配置文件中解析
    else {
      Object[] argsToResolve = null;
      // 尝试从缓存中获取bean的构造函数以及参数
      // 解析bean定义的构造函数较为耗时,因此在完成解析后会将解析后的构造函数以及参数放入BeanDefinition中的相关字段作为缓存
      // mbd.resolvedConstructorOrFactoryMethod存放的是构造函数
      // mbd.resolvedConstructorArguments存放的是处理后的构造函数参数
      // mbd.preparedConstructorArguments存放的是原生的构造函数参数(参数类型未经过处理)
      synchronized (mbd.constructorArgumentLock) {
        constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
        if (constructorToUse != null && mbd.constructorArgumentsResolved) {
          // Found a cached constructor...
          argsToUse = mbd.resolvedConstructorArguments;
          if (argsToUse == null) {
            argsToResolve = mbd.preparedConstructorArguments;
          }
        }
      }
      // 如果缓存中存在
      if (argsToResolve != null) {
        // 解析参数类型,将构造参数的类型转换为最终的类型
        // eg: 构造函数A(int, int)
        // 通过此方法后就会把配置中的("1", "1")转换为(1, 1)
        argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
      }
    }

    // 缓存中不存在
    if (constructorToUse == null) {
      // Need to resolve the constructor.
      boolean autowiring =
          (chosenCtors != null
              || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
      // 存放解析后的构造函数参数的值
      ConstructorArgumentValues resolvedValues = null;

      int minNrOfArgs;
      if (explicitArgs != null) {
        minNrOfArgs = explicitArgs.length;
      } else {
        // 提取配置文件中的构造函数参数
        ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
        resolvedValues = new ConstructorArgumentValues();
        minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
      }

      // Take specified constructors, if any.
      // 获取bean的class类的所有构造函数
      Constructor<?>[] candidates = chosenCtors;
      if (candidates == null) {
        Class<?> beanClass = mbd.getBeanClass();
        try {
          candidates =
              (mbd.isNonPublicAccessAllowed()
                  ? beanClass.getDeclaredConstructors()
                  : beanClass.getConstructors());
        } catch (Throwable ex) {
          throw new BeanCreationException(
              mbd.getResourceDescription(),
              beanName,
              "Resolution of declared constructors on bean Class ["
                  + beanClass.getName()
                  + "] from ClassLoader ["
                  + beanClass.getClassLoader()
                  + "] failed",
              ex);
        }
      }
      // 排序给定的构造函数,public构造函数优先,参数数量降序
      AutowireUtils.sortConstructors(candidates);
      int minTypeDiffWeight = Integer.MAX_VALUE;
      Set<Constructor<?>> ambiguousConstructors = null;
      LinkedList<UnsatisfiedDependencyException> causes = null;

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

        // 如果已经找到选用的构造函数,并且构造函数所需的参数个数小于配置的构造函数参数个数则终止,因为构造函数已经按照参数个数降序
        if (constructorToUse != null && argsToUse.length > paramTypes.length) {
          // Already found greedy constructor that can be satisfied ->
          // do not look any further, there are only less greedy constructors left.
          break;
        }
        if (paramTypes.length < minNrOfArgs) {
          continue;
        }

        ArgumentsHolder argsHolder;
        // 构造函数参数从配置文件中获取的情况
        if (resolvedValues != null) {
          // 有参数则直接根据值构造对应类型的参数
          try {
            String[] paramNames =
                ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
            if (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 constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
            }
            // Swallow and try next constructor.
            if (causes == null) {
              causes = new LinkedList<UnsatisfiedDependencyException>();
            }
            causes.add(ex);
            continue;
          }
        }
        // 构造函数参数从getBean方法传入的情况
        else {
          // Explicit arguments given -> arguments length must match exactly.
          // 对于构造函数从getBean方法传入的情况,参数数目必须精确匹配
          if (paramTypes.length != explicitArgs.length) {
            continue;
          }
          argsHolder = new ArgumentsHolder(explicitArgs);
        }

        // 检测是否有不确定性的构造函数存在,例如不同构造函数的参数为父子关系
        int typeDiffWeight =
            (mbd.isLenientConstructorResolution()
                ? argsHolder.getTypeDifferenceWeight(paramTypes)
                : argsHolder.getAssignabilityWeight(paramTypes));
        // Choose this constructor if it represents the closest match.
        // 选择最为接近的匹配作为构造函数
        if (typeDiffWeight < minTypeDiffWeight) {
          constructorToUse = candidate;
          argsHolderToUse = argsHolder;
          argsToUse = argsHolder.arguments;
          minTypeDiffWeight = typeDiffWeight;
          ambiguousConstructors = null;
        } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
          if (ambiguousConstructors == null) {
            ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
            ambiguousConstructors.add(constructorToUse);
          }
          ambiguousConstructors.add(candidate);
        }
      }

      if (constructorToUse == null) {
        if (causes != null) {
          UnsatisfiedDependencyException ex = causes.removeLast();
          for (Exception cause : causes) {
            this.beanFactory.onSuppressedException(cause);
          }
          throw ex;
        }
        throw new BeanCreationException(
            mbd.getResourceDescription(),
            beanName,
            "Could not resolve matching constructor "
                + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
      } else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
        throw new BeanCreationException(
            mbd.getResourceDescription(),
            beanName,
            "Ambiguous constructor matches found in bean '"
                + beanName
                + "' "
                + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): "
                + ambiguousConstructors);
      }

      if (explicitArgs == null) {
        // 将解析的构造函数加入缓存
        argsHolderToUse.storeCache(mbd, constructorToUse);
      }
    }

    // 确定了构造函数以及参数后,使用构造函数对bean进行实例化
    try {
      Object beanInstance;

      if (System.getSecurityManager() != null) {
        final Constructor<?> ctorToUse = constructorToUse;
        final Object[] argumentsToUse = argsToUse;
        beanInstance =
            AccessController.doPrivileged(
                new PrivilegedAction<Object>() {
                  @Override
                  public Object run() {
                    return beanFactory
                        .getInstantiationStrategy()
                        .instantiate(mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
                  }
                },
                beanFactory.getAccessControlContext());
      } else {
        beanInstance =
            this.beanFactory
                .getInstantiationStrategy()
                .instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
      }

      // 将构建的实例加入BeanWrapper中
      bw.setWrappedInstance(beanInstance);
      return bw;
    } catch (Throwable ex) {
      throw new BeanCreationException(
          mbd.getResourceDescription(), beanName, "Bean instantiation via constructor failed", ex);
    }
  }