欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring源码:工厂方法实例化Bean

程序员文章站 2022-05-21 22:55:09
...

源代码

该函数在类ConstructorResolver(该类的作用:构造函数和工厂方法解析的代理,主要作用通过参数匹配执行构造函数解析)为了简化分析,去除了不必要的异常和日志。

public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {

  BeanWrapperImpl bw = new BeanWrapperImpl();
  // 把BeanFactory的框架内置和自定义PropertyEditor放到BeanWrapperImpl中
  this.beanFactory.initBeanWrapper(bw);

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

  // 第一部分:获取工厂类class、工厂类方法、参数
  String factoryBeanName = mbd.getFactoryBeanName();
  if (factoryBeanName != null) {
    // 加载标签factory-bean指向的class,一般说含有factory-bean标签时,其指向的class是非静态
    factoryBean = this.beanFactory.getBean(factoryBeanName);
    factoryClass = factoryBean.getClass();
    isStatic = false;
  } else {
      // 不含有factory-bean标签,工厂Bean含有创建Bean的静态方法
      factoryBean = null;
      factoryClass = mbd.getBeanClass();
      isStatic = true;
  }
    Method factoryMethodToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;

    // 若getBean方法调用时指定了方法参数,则直接使用
    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    } else {
        // 若getBean方法调用时没有指定方法参数,则尝试从配置文件中加载
        Object[] argsToResolve = null;
        // 对mbd的构造函数加锁
        synchronized (mbd.constructorArgumentLock) {
            // 从缓存中取构造函数或工厂方法
            factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
            // 若取到构造函数或工厂方法,且构造函数的所有参数已解析
            if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                // 从缓存中取解析的参数
                argsToUse = mbd.resolvedConstructorArguments;
                if (argsToUse == null) {
                    // 若从缓存中没有取到解析的参数,就取配置文件中的参数
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        if (argsToResolve != null) {
            // 解析配置文件中的参数类型,如参数类型转换
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
        }
    }

    // 第二部分:
    // 若没有被缓存的构造函数或工厂方法,且参数也无法获取,重新分析
    if (factoryMethodToUse == null || argsToUse == null) {
        factoryClass = ClassUtils.getUserClass(factoryClass);
        // 根据mdb的nonPublicAccessAllowed字段获取候选的方法集合rawCandidates
        Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
        // 对 rawCandidates 集合进一步筛选与工厂方法名相同的的方法集合candidateSet
        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 {
            // 提取配置文件中的配置的构造函数参数
            ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
            // 用于承载解析后的构造函数参数的值
            resolvedValues = new ConstructorArgumentValues();
            // 能解析到的参数个数(参考分析2)
            minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
        }

        LinkedList<UnsatisfiedDependencyException> causes = null;
        for (Method candidate : candidates) {
            Class<?>[] paramTypes = candidate.getParameterTypes();
            // 若匹配到的方法的参数个数大于等于配置文件配置的参数个数
            if (paramTypes.length >= minNrOfArgs) {
                ArgumentsHolder argsHolder;
                if (resolvedValues != null) {
                    // Resolved constructor arguments: type conversion and/or autowiring necessary.
                    String[] paramNames = null;
                    // 获取参数名称解析器
                    ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                    if (pnd != null) {
                        // 解析candidate方法中的参数
                        paramNames = pnd.getParameterNames(candidate);
                    }
                    // 给定已解析的构造函数参数值,创建一个参数数组来调用构造函数或工厂方法
                    argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
                } 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;
                } 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);
                }
            }
        } //for (Method candidate : candidates) 

        if (factoryMethodToUse == null) {
            // 抛出异常,没有找到对应的工厂方法
        } else if (void.class == factoryMethodToUse.getReturnType()) {
            // 抛出异常,需要返回值
        } else if (ambiguousFactoryMethods != null) {
            // 抛出异常,模糊的工厂方法与bean中匹配了
        }

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

    //
    Object beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
    if (beanInstance == null) {
        return null;
    }
    bw.setBeanInstance(beanInstance);
    return bw;
}

分析:

  1. RootBeanDefinition的几个属性

    //缓存已解析的构造函数或工厂方法
    Object resolvedConstructorOrFactoryMethod;
    
    // 将构造函数参数标记为是否已解析
    boolean constructorArgumentsResolved = false;
    
    // 缓存完全解析的构造函数参数
    Object[] resolvedConstructorArguments;
    
    // 缓存部分准备好的构造函数参数,即配置文件中配置的参数
    Object[] preparedConstructorArguments;
  2. 解析配置文件中的参数函数resolveConstructorArguments,该函数在类ConstructorResolver中,

    private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
      // 获取类型转换器
      TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
      TypeConverter converter = (customConverter != null ? customConverter : bw);
      BeanDefinitionValueResolver valueResolver =
            new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
    
       // 配置文件中参数的个数
      int minNrOfArgs = cargs.getArgumentCount();
    
      for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
          // TODO
          int index = entry.getKey();
          if (index > minNrOfArgs) {
              minNrOfArgs = index + 1;
          }
          ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
          if (valueHolder.isConverted()) {
              // 若已经转换过
              resolvedValues.addIndexedArgumentValue(index, valueHolder);
          } else {
              // 没有转换过
              // BeanDefinitionValueResolver类resolveValueIfNecessary方法,主要解析Array,Set,Map,props和字符串类型的间接引用
              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;
    }
  3. 实例化Bean,该方法在SimpleInstantiationStrategy类中,通过反射调用

    public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, Object... args) {
       ReflectionUtils.makeAccessible(factoryMethod);
       Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();
       try {
           currentlyInvokedFactoryMethod.set(factoryMethod);
           return factoryMethod.invoke(factoryBean, args);
       } finally {
           if (priorInvokedFactoryMethod != null) {
               currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
           } else {
               currentlyInvokedFactoryMethod.remove();
           }
       } // finally
    }