/**
   * 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;
  }
  /** 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;
  }