深入理解Spring IOC(五) 、 创建bean实例(下)

简介: 深入理解Spring IOC(五) 、 创建bean实例(下)

9.1


代码块10
protected BeanWrapper instantiateUsingFactoryMethod(
      String beanName, RootBeanDefinition mbd, Object[] explicitArgs) {
    return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}


我们可以看到,这里只是直接调用了ConstructorResolver中的instantiateUsingFactoryMethod,这个方法是个非常长的同时也是个比较复杂的方法,我们直接来到ConstructorResolver中来看这个方法:


代码块11
public BeanWrapper instantiateUsingFactoryMethod(
      final String beanName, final RootBeanDefinition mbd, final Object[] explicitArgs) {
  // new 一个bw, bw也是方法的结果
  BeanWrapperImpl bw = new BeanWrapperImpl();
  // 对bw进行起码的初始化,这句可以先跳过,你只要知道是个起码的初始化即可
  this.beanFactory.initBeanWrapper(bw);
  Object factoryBean;
  Class<?> factoryClass;
  boolean isStatic;
  // 拿到factoryBean的Name,xml中对应factory-bean属性
  String factoryBeanName = mbd.getFactoryBeanName();
  if (factoryBeanName != null) {
    // 如果factoryBeanName 和 目标bean的名称是一样的,则直接抛异常
    // 这个是指xml中bean标签的factory-bean和id属性值不能一样
    if (factoryBeanName.equals(beanName)) {
      throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
          "factory-bean reference points back to the same bean definition");
    }
    // 拿到factoryBeanName对应的bean,即beanName对应bean的factory类
    factoryBean = this.beanFactory.getBean(factoryBeanName);
    // 是null抛异常,因为根本没有这个factoryBean或者其创建出来的对象
    if (factoryBean == null) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
          "factory-bean '" + factoryBeanName + "' (or a BeanPostProcessor involved) returned null");
    }
    factoryClass = factoryBean.getClass();
    isStatic = false;
  }else {
    // 这个else代码块是静态工厂的处理,静态工厂不会在xml中指定factory-bean
    // 不知道类是哪个的话则抛异常
    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 {
  // 这个else 代码块主要是在拿已经解析并使用过的方法和方法参数的缓存
    Object[] argsToResolve = null;
    synchronized (mbd.constructorArgumentLock) {
      // 注意哈,这里便体现出了RootBeanDefiniti缓存的作用了
      // 拿解析过的构造方法或是工厂方法
      factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
      // 已解析过的不为空 && mbd构造方法参数也是有的
      if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
        // 设置argsToUse为mbd解析过的构造方法的参数的缓存
        argsToUse = mbd.resolvedConstructorArguments;
        // 这个是候选的用来解析的
        if (argsToUse == null) {
          argsToResolve = mbd.preparedConstructorArguments;
        }
      }
    }
    // 1. 解析要使用的参数为需要的类型
    if (argsToResolve != null) {
      argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);
    }
  }
  if (factoryMethodToUse == null || argsToUse == null) {
    // 这段代码主要是在找哪个方法是静态工厂方法
    factoryClass = ClassUtils.getUserClass(factoryClass);
    // 拿到factoryClass的所有方法
    Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
    List<Method> candidateSet = new ArrayList<Method>();
    for (Method candidate : rawCandidates) {
      // 是静态方法 && 名字和mbd的工厂方法一样
      // 因为即使是静态并且名字是同一个,也存在可能有个多个重载的情况
      // 所以需要存到candidateSet进行进一步的筛选
      if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
        candidateSet.add(candidate);
      }
    }
    // candidateSet转为数组并排序
    Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]);
    // 给方法排序,public排在非public之前,如果都是public,则参数多的排在前
    AutowireUtils.sortFactoryMethods(candidates);
    // 解析过的参数
    ConstructorArgumentValues resolvedValues = null;
    // 是否为构造器注入,这里一般都是false
    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 {
      // 拿到beanDefinition中解析到的xml中定义的构造方法参数
      ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
      resolvedValues = new ConstructorArgumentValues();
      // 2.解析参数,并返回参数个数(解析体现在需要把“1”这样的string转化为了int)
      minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
    }
    List<Exception> causes = null;
    // 通过各种方式确定最终要使用的工厂方法是哪个,以及其中的参数
    // 遍历candidates
    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);
            }
            // 3.解析参数
            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);
            }
            // i为最后一个,&& argsHolderToUse为null (还没找到合适的参数)
            if (i == candidates.length - 1 && argsHolderToUse == null) {
              // 如果有异常,此时也就该抛异常了
              if (causes != null) {
                for (Exception cause : causes) {
                  this.beanFactory.onSuppressedException(cause);
                }
              }
              throw ex;
            }else {
              // 如果有异常,就记录下来
              if (causes == null) {
                causes = new LinkedList<Exception>();
              }
              causes.add(ex);
              continue;
            }
          }
        }else {
          if (paramTypes.length != explicitArgs.length) {
            continue;
          }
          argsHolder = new ArgumentsHolder(explicitArgs);
        }
        // 这个就是开始AbstractBeanDefinition中lenientConstructorResolution
        // 那个属性影响到的地方,具体体现在:如果是true,代表只要你的值转换过的类型可以和需要的类型
        // 能匹配上,就是你这个方法了。比如说:getInstance(Integer age),此时xml定义了age为18的参数,而由于xml中定义的参数都会被解析
        // 成String,因此需要转化,如果lenientConstructorResolution为true,则这里就可以匹配上这个方法
        // 因为18可以被转为Integer,如果是false,就不能匹配上这个方法了
        int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
        // 根据权重选出最合适的方法和参数,权重小则说明越合适
        // minTypeDiffWeight的值此时是Integer.MAX_VALUE
        if (typeDiffWeight < minTypeDiffWeight) {
          factoryMethodToUse = candidate;
          argsHolderToUse = argsHolder;
          argsToUse = argsHolder.arguments;
          minTypeDiffWeight = typeDiffWeight;
          ambiguousFactoryMethods = null;
        // factoryMethodToUse不为null && 类型差异权重相同 && 不是宽松构造函数解析模式 && 候选方法的参数类型
        // 和factoryMethodToUse的长度相同 && 候选方法数组和factoryMethodToUse的参数类型不一样
        // 注意哈:typeDiffWeight 是不可能比 minTypeDiffWeight 大的,具体原因可以去计算typeDiffWeight
        // 的方法里看
        }else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&
            !mbd.isLenientConstructorResolution() &&
            paramTypes.length == factoryMethodToUse.getParameterTypes().length &&
            !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
          // 添加到ambiguousFactoryMethods用作后续的抛异常用
          if (ambiguousFactoryMethods == null) {
            ambiguousFactoryMethods = new LinkedHashSet<Method>();
            ambiguousFactoryMethods.add(factoryMethodToUse);
          }
          ambiguousFactoryMethods.add(candidate);
        }
      }
    }
    // 如果此时factoryMethodToUse还是null,则抛异常
    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") + ".");
    // 如果factoryMethodToUse返回值类型是void,则抛异常
    }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!");
    // 如果ambiguousFactoryMethods不是null,则抛异常
    }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);
    }
    // 将解析出来的参数和方法存到mbd的缓存中
    // 应该还知道mbd是个啥玩意吧?不知道的话赶紧回去看一看
    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 = beanFactory.getInstantiationStrategy().instantiate(
          mbd, beanName, beanFactory, factoryBean, factoryMethodToUse, argsToUse);
    }
    if (beanInstance == null) {
      return null;
    }
    bw.setWrappedInstance(beanInstance);
    return bw;
  }
  catch (Throwable ex) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  }
}


确实是个无比长的方法,所以我都是尽可能的是在代码内做解释,不用让你在方法这么长的情况下还得上下切屏幕,即使这样子,这也依然不那么简单,很多人也是被这个代码劝退的,看我文章的读者,你如果看到这里了,我觉得你还是有必要坚持一下的,因为已经到这样的地方了,这个过了,剩下的就都不难了。


11.1


这里主要是对参数的解析转换,即把给定的参数转化成正确的类型


代码块12
private Object[] resolvePreparedArguments(
      String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) {
  // 如果methodOrCtor是Method或者Constructor的实例,则拿到它的参数
  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);
  // 本方法的result
  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);
    }
    // 从这里能看出来,做的事情其实就是把“1”这样的变成了1,
    // 即把参数转化成真正需要的类型
    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;
}


11.2


这里也是解析参数,但是这里是在解析xml中给定的参数,并返回所需要参数的最小个数,在这里,还有可能去寻找所依赖的bean


代码块13
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();
  // 这里是那种标签里带着index配置的的参数,如果没有配这个index
  // 那将不会走这个循环
  for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
    int index = entry.getKey();
    // index不能小于0
    if (index < 0) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
          "Invalid constructor argument index: " + index);
    }
    // index大于上面的最少需要参数个数,则最小的参数个数需要+1
    if (index > minNrOfArgs) {
      minNrOfArgs = index + 1;
    }
    // 拿到对应的value
    ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
    // 进行转化
    if (valueHolder.isConverted()) {
      // 如果以及转化过,则直接添加到resolvedValues中
      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中
      resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
    }
  }
  // 这里是那种标签里带着index配置的的参数
  for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
    // 进行转化,逻辑和上面相同,只不过添加到了resolvedValues中
    // 的genericArgumentValue中
    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;
}


11.3


代码块14
    // 创建工厂方法或者是构造方法的参数
  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);
  // args是本方法return的结果
  ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
  // usedValueHolders这个是已经解析出来的,用作过滤用
  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);
    // 根据下标去拿构造方法的参数
    ConstructorArgumentValues.ValueHolder valueHolder =
        resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
    // 如果没有找到需要的参数,并且不允许自动装配,则去尝试使用下一个无类型参数
    // 注:无类型参数的名称和类型必须是匹配的
    if (valueHolder == null && !autowiring) {
      valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
    }
    if (valueHolder != null) {
      // 此时已经找到一个“说不定能用”的参数
      usedValueHolders.add(valueHolder);
      // 拿到这个参数的值
      Object originalValue = valueHolder.getValue();
      Object convertedValue;
      // 如果参数类型已经被转化过则直接使用(其实就是加到args对应的位置)
      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));
          args.resolveNecessary = true;
          // 将转换后的参数添加到args对应位置
          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 {
      // 找不到明确的参数,并且不允许自动装配,则抛出异常
      if (!autowiring) {
        throw new UnsatisfiedDependencyException(
            mbd.getResourceDescription(), beanName, paramIndex, paramType,
            "Ambiguous " + methodType + " argument types - " +
            "did you specify the correct bean references as " + methodType + " arguments?");
      }
      // 上面的是处理xml的,这里的是注解的,指的是@Autowired标在构造方法上面,需要处理参数的bean
      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;
}


代码块11的便说完了,我不知道有多少人能看到这里,说实话,写到这里,作者我自己也是崩溃的,我崩溃的地方不是我觉得它有多么的难,而是我实在没办法把这个方法搞得像大白话一样让你一下子能看懂,看这种源码,最崩溃的就是明明一个方法已经非常的长了,但是人家还一个套一个,你看完了里面套的一个巨长无比的方法之后回到原来的方法发现只前进了一行,然后很多人就被劝退了😂。其实我为了你看着容易,代码块11里有的方法我没有列出来,但是我的github上面的源码是有注释的,你按着我的引导对着源码看一遍,然后自己再一遍一遍的跟,会更容易一些。坚持真的很不容易,所以能到这里的人,作为作者,为你们点个赞,让我们一起加油。

说了一点点自己的感触哈,代码块9.1这个调用工厂方法创建bean已经完了,然后是9.2,9.2调用的代码和9.1的一样长,但是套路几乎是一样的,所以要是你真的看懂了上面的,下面的这个也就很容易了。


9.2


代码块15
// 使用构造方法创建bean
public BeanWrapper autowireConstructor(
      final String beanName, final RootBeanDefinition mbd, Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
    // 创建并初始化BeanWrapper
  BeanWrapperImpl bw = new BeanWrapperImpl();
  this.beanFactory.initBeanWrapper(bw);
  // constructorToUse是要去使用的构造方法,argsHolderToUse是要用的构造方法的参数
  Constructor<?> constructorToUse = null;
  ArgumentsHolder argsHolderToUse = null;
  Object[] argsToUse = null;
  // 如果explicitArgs不为null,那最终要用的参数就为explicitArgs
  if (explicitArgs != null) {
    argsToUse = explicitArgs;
  }else {
    Object[] argsToResolve = null;
    synchronized (mbd.constructorArgumentLock) {
      // 先尝试从mbd的缓存拿解析过的构造方法和其对应的参数
      // 注意哈,这块为什么会和之前那个根据工厂方法创建bean用的是一个mbd的变量做缓存的原因是:
      // 一个对象同时只能使用构造方法和工厂方法中的一个去创建(不理解这里的可以多看几遍源码)
      constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
      // 构造方法不为空 && 并且构造函数的参数解析过
      if (constructorToUse != null && mbd.constructorArgumentsResolved) {
        // 缓存中拿已经解析出来的参数
        argsToUse = mbd.resolvedConstructorArguments;
        // 如果已经解析的为空,则去拿候选解析的
        if (argsToUse == null) {
          argsToResolve = mbd.preparedConstructorArguments;
        }
      }
    }
    // 如果argsToResolve不为null,把参数解析为正确的类型,上面已讲过这个方法
    if (argsToResolve != null) {
      argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
    }
  }
  // 如果上面没有从缓存中拿到,则尝试去解析一个最合适的构造方法
  if (constructorToUse == null) {
    boolean autowiring = (chosenCtors != null ||
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    ConstructorArgumentValues resolvedValues = null;
    // 构造方法参数个数
    int minNrOfArgs;
    // 如果给定的参数数组不是null,则使用给定的参数数组的长度
    if (explicitArgs != null) {
      minNrOfArgs = explicitArgs.length;
    }else {
      // 这里的cargs其实就是我们xml定义的constructor-arg的东西
      ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
      resolvedValues = new ConstructorArgumentValues();
      minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
    }
    // 如果这时候方法参数里的构造方法数组是空的,那么
    // 就去拿beanClass的构造方法
    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排在非public之前,如果都是public,则参数多的排在前
    AutowireUtils.sortConstructors(candidates);
    // 这块权重的这个套路和之前的是一样的
    int minTypeDiffWeight = Integer.MAX_VALUE;
    Set<Constructor<?>> ambiguousConstructors = null;
    List<Exception> 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) {
        // 跳出循环不再查找,因为对于排序过后的数组来说,现在的constructorToUse已经是最合适的了
        break;
      }
      // 如果这个下标的构造方法的参数小于我们所需要的参数个数,则直接跳过这个构造方法
      if (paramTypes.length < minNrOfArgs) {
        continue;
      }
      ArgumentsHolder argsHolder;
      if (resolvedValues != null) {
        try {
          // 这块是去拿本下标构造方法参数的真正的名字
          String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
          if (paramNames == null) {
            // 如果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);
          }
          // 这个是指到candidates最后一个都还没找到可以用的构造方法,则抛出异常
          if (i == candidates.length - 1 && constructorToUse == null) {
            if (causes != null) {
              for (Exception cause : causes) {
                this.beanFactory.onSuppressedException(cause);
              }
            }
            throw ex;
          // 否则在这里吃掉异常,继续找下一个
          }else {
            // Swallow and try next constructor.
            if (causes == null) {
              causes = new LinkedList<Exception>();
            }
            causes.add(ex);
            continue;
          }
        }
      }else {
        // 参数的长度都不相同,肯定不是一个方法,则直接跳过
        if (paramTypes.length != explicitArgs.length) {
          continue;
        }
        argsHolder = new ArgumentsHolder(explicitArgs);
      }
      // 权重,这里这个参数的意义和之前工厂方法创建对象的意义是一样的,
      // 不明白的可以翻上去看看
      int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
          argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
      // 根据权重选出最合适的方法和参数,权重小则说明越合适
      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) {
      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);
    }
  }
  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);
    }
    // 返回结果bw
    bw.setWrappedInstance(beanInstance);
    return bw;
  }
  catch (Throwable ex) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  }
}


这个方法和代码块11的整体套路其实是类似的。当然,这也是这个系列文章中最后一个大方法,到这里,剩下的代码对你来说都不会再有什么难度~


9.3


// 使用默认构造方法
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
  try {
    Object beanInstance;
    final BeanFactory parent = this;
    // 特权创建或者普通创建,最后都是在调用构造方法
    if (System.getSecurityManager() != null) {
      beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
          return getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
      }, getAccessControlContext());
    }
    else {
      beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    }
    BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    initBeanWrapper(bw);
    return bw;
  }
  catch (Throwable ex) {
    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
  }
}


这个方法其实还是简单很多的,我没有把里面的再往出列,你可以去自己跟一下,相信此时你的实力,看这个方法对你来说还是小意思的。

至此,代码块8里面createBeanInstance方法也就讲完了,剩下的我们下一篇继续。

目录
相关文章
|
4天前
|
XML Java 数据格式
Spring框架入门:IoC与DI
【5月更文挑战第15天】本文介绍了Spring框架的核心特性——IoC(控制反转)和DI(依赖注入)。IoC通过将对象的创建和依赖关系管理交给容器,实现解耦。DI作为IoC的实现方式,允许外部注入依赖对象。文章讨论了过度依赖容器、配置复杂度等常见问题,并提出通过合理划分配置、使用注解简化管理等解决策略。同时,提醒开发者注意过度依赖注入和循环依赖,建议适度使用构造器注入和避免循环引用。通过代码示例展示了注解实现DI和配置类的使用。掌握IoC和DI能提升应用的灵活性和可维护性,实践中的反思和优化至关重要。
18 4
|
4天前
|
安全 Java Spring
Spring框架中的单例Bean是线程安全的吗?
Spring框架中的单例Bean是线程安全的吗?
10 1
|
4天前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
22 0
|
4天前
|
XML 前端开发 Java
【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)
【JavaEE】深入了解Spring中Bean的可见范围(作用域)以及前世今生(生命周期)
7 0
|
4天前
|
存储 缓存 Java
【JavaEE】Spring中注解的方式去获取Bean对象
【JavaEE】Spring中注解的方式去获取Bean对象
3 0
|
4天前
|
存储 Java 对象存储
【JavaEE】Spring中注解的方式去存储Bean对象
【JavaEE】Spring中注解的方式去存储Bean对象
7 0
|
4天前
|
存储 Java 对象存储
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
9 0
|
4天前
|
XML Java 程序员
Spring特性之二——IOC控制反转
Spring特性之二——IOC控制反转
16 4
|
4天前
|
安全 Java 开发者
在Spring框架中,IoC和AOP是如何实现的?
【4月更文挑战第30天】在Spring框架中,IoC和AOP是如何实现的?
24 0
|
4天前
|
XML Java 程序员
什么是Spring的IoC容器?
【4月更文挑战第30天】什么是Spring的IoC容器?
20 0