Spring IOC - 推断构造方法

一、前言

        上文解析了Bean生命周期的实例化阶段,其中bean真正开始实例化的核心代码位于方法AbstractAutowireCapableBeanFactory#createBeanInstance中,这里也是spring推断构造方法的核心所在。

二、整体介绍

        首先看下方法的源码及注释如下,下面我们再逐行解析。

// 使用适当的实例化策略为指定的bean创建一个新实例:工厂方法、构造函数自动装配或简单实例化
// 创建bean的实例,这里也是spring推断构造方法的核心所在
// args:表示程序员通过getBean传入的参数,如果使用getBean(Class<?> requireType,Object[] args),那么传入的参数就会传入到这里
// 这个参数是用于构造函数或工厂方法调用的显示参数
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
   // Make sure bean class is actually resolved at this point.
   // 获取bean的Class对象
   Class<?> beanClass = resolveBeanClass(mbd, beanName);

   if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
            "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
   }

   // 通过bd中提供的instanceSupplier来获取一个对象
   // 正常bd中都不会有这个instanceSupplier属性,这里也是Spring提供的一个扩展点,但实际上不常用
   Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
   if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
   }

   // 如果工厂方法不为null,则使用工厂方法初始化策略
   // bd中提供了factoryMethodsName属性,那么要使用工厂方法的方法来创建对象
   // 工厂方法又会区分静态工厂方法跟实例工厂方法
   if (mbd.getFactoryMethodName() != null) {
      // 如果使用了工厂方法,则调用工厂方法创建bean实例。@Bean注解创建的实例会进入这里
      return instantiateUsingFactoryMethod(beanName, mbd, args);
   }

   // Shortcut when re-creating the same bean...
   // 在原型模式下,如果已经创建过一次这个Bean了,那么就不需要再次推断构造函数了
   // 是否推断过构造函数
   boolean resolved = false;
   // 构造函数是否需要进行注入
   boolean autowireNecessary = false;
   if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
         // 一个类里面有多个构造函数,每个构造函数都有不同的参数,所以调用前需根据参数锁定要调用
         // 的构造函数或工厂方法
         if (mbd.resolvedConstructorOrFactoryMethod != null) {
            resolved = true;
            autowireNecessary = mbd.constructorArgumentsResolved;
         }
      }
   }
   // 如果已经解析过则使用解析好的构造函数方法,不需要再次锁定
   if (resolved) {
      if (autowireNecessary) {
         // 构造函数自动注入
         return autowireConstructor(beanName, mbd, null, null);
      }
      else {
         // 使用默认构造函数进行构造
         return instantiateBean(beanName, mbd);
      }
   }

   // Candidate constructors for autowiring?
   // 需要根据参数解析构造函数
   Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
   if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      // 构造函数自动注入
      return autowireConstructor(beanName, mbd, ctors, args);
   }

   // Preferred constructors for default construction?
   // 获取首选构造函数,作为默认构造器
   ctors = mbd.getPreferredConstructors();
   if (ctors != null) {
      return autowireConstructor(beanName, mbd, ctors, null);
   }

   // No special handling: simply use no-arg constructor.
   // 没有什么特殊的处理:简单使用无参构造方法
   return instantiateBean(beanName, mbd);
}

        总体流程总结如下:

  1. AbstractAutowireCapableBeanFactory类中的createBeanInstance()方法会去创建一个Bean实例
  2. 根据BeanDefinition加载类得到Class对象
  3. 如果BeanDefinition绑定了一个Supplier,那就调用Supplier的get方法得到一个对象并直接返回
  4. 如果BeanDefinition中存在factoryMethodName,那么就调用该工厂方法得到一个bean对象并返回
  5. 如果BeanDefinition已经自动构造过了,那就调用autowireConstructor()自动构造一个对象
  6. 调用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法得到哪些构造方法是可以用的
  7. 如果存在可用得构造方法,或者当前BeanDefinition的autowired是AUTOWIRE_CONSTRUCTOR,或者BeanDefinition中指定了构造方法参数值,或者创建Bean的时候指定了构造方法参数值,那么就调用**autowireConstructor()**方法自动构造一个对象
  8. 最后,如果不是上述情况,就根据无参的构造方法实例化一个对象

三、Supplier

        Supplier是Spring 用来创建bean的一种方式,但是不常见。即将beanDefiniton属性instanceSupplier设置一个可以返回实例的方法,那么通过该beanDefinition生成实例bean时,会调用Supplier的getObject方法直接返回。示例如下:

public class Analsis {

   public static void main(String[] args) {
      DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
      beanDefinition.setBeanClass(User.class);
      beanDefinition.setInstanceSupplier(Teacher::new);
      beanFactory.registerBeanDefinition("user", beanDefinition);
      System.out.println(beanFactory.getBean("user"));
   }
}

        示例返回结果为:com.test.Teacher@6d4b1c02,虽然设置的beanClass属性为User.class,但是返回的bean实例还是Teacher实例。

四、@Bean

        这里阐述的是通过beanDefinition中的factoryMethodName属性来创建bean实例。@Bean标记的方法名就是factoryMethodName,其所在的父类名称就是属性factoryBeanName。通过@Bean标记的实例,其实在解析生成BeanDefinition时,就已经对关键属性进行赋值了,后续的创建过程无非就是根据其属性来实例化,这里有个关键属性:factoryMethodToIntrospect,即通过内省获取的工厂方法,其实到最后就是通过反射机制调用该方法创建实例。

五、推动构造函数

        这里的逻辑是一个扩展点,即调用实现了SmartInstantiationAwareBeanPostProcessor接口的determineCandidateConstructors方法。而AutowiredAnnotationBeanPostProcessor实现了该接口,其源码及注释如下:

public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
      throws BeanCreationException {

   // Let's check for lookup methods here...
   if (!this.lookupMethodsChecked.contains(beanName)) {
      if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {
         try {
            Class<?> targetClass = beanClass;
            do {
               //遍历targetClass中的method,查看是否写了@Lookup方法
               ReflectionUtils.doWithLocalMethods(targetClass, method -> {
                  Lookup lookup = method.getAnnotation(Lookup.class);
                  if (lookup != null) {
                     Assert.state(this.beanFactory != null, "No BeanFactory available");
                     //将当前method封装成LookOverride并设置到BeanDefinition的methodOverrides中
                     LookupOverride override = new LookupOverride(method, lookup.value());
                     try {
                        RootBeanDefinition mbd = (RootBeanDefinition)
                              this.beanFactory.getMergedBeanDefinition(beanName);
                        mbd.getMethodOverrides().addOverride(override);
                     }
                     catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(beanName,
                              "Cannot apply @Lookup to beans without corresponding bean definition");
                     }
                  }
               });
               targetClass = targetClass.getSuperclass();
            }
            while (targetClass != null && targetClass != Object.class);

         }
         catch (IllegalStateException ex) {
            throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
         }
      }
      this.lookupMethodsChecked.add(beanName);
   }

   // Quick check on the concurrent map first, with minimal locking.
   //决定一组构造方法的逻辑代码,candidateConstructorsCache是一个构造方法候选者的集合,就是说如果找到了符合条件的构造方法
   //都会缓存到这个集合中,表示是符合条件的构造方法的候选者集合
   //这里先从缓存中去取,如果缓存中没有,就去推断出符合的记录添加到缓存中
   Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
   if (candidateConstructors == null) {
      // Fully synchronized resolution now...
      synchronized (this.candidateConstructorsCache) {
         //先从缓存中去取,如果有,就直接返回,如果没有,就去找
         candidateConstructors = this.candidateConstructorsCache.get(beanClass);
         if (candidateConstructors == null) {
            Constructor<?>[] rawCandidates;
            try {
               //这个是得到一个Bean中的声明的所有的构造方法列表,是一个数组,数组里面是bean中的所有构造方法
               rawCandidates = beanClass.getDeclaredConstructors();
            }
            catch (Throwable ex) {
               throw new BeanCreationException(beanName,
                     "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                     "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
            }
            //构建一个候选者列表的构造方法集合
            List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
            //用来记录@AutoWired标记并且required为true的构造方法,一个类中只能有一个required为true的构造方法
            Constructor<?> requiredConstructor = null;
            //用来记录默认无参构造方法
            Constructor<?> defaultConstructor = null;
            //kotlin相关,不用管
            Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
            int nonSyntheticConstructors = 0;
            //遍历每个构造方法
            for (Constructor<?> candidate : rawCandidates) {
               if (!candidate.isSynthetic()) {
                  //记录下一普通构造方法
                  nonSyntheticConstructors++;
               }
               else if (primaryConstructor != null) {
                  continue;
               }
               //当前遍历的构造方法是否被@AutoWired注解标记
               MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
               if (ann == null) {
                  //如果beanClass是代理类,则得到被代理类的类型
                  //然后去看被代理类中对应的构造方法是否有@AutoWired注解
                  Class<?> userClass = ClassUtils.getUserClass(beanClass);
                  if (userClass != beanClass) {
                     try {
                        Constructor<?> superCtor =
                              userClass.getDeclaredConstructor(candidate.getParameterTypes());
                        ann = findAutowiredAnnotation(superCtor);
                     }
                     catch (NoSuchMethodException ex) {
                        // Simply proceed, no equivalent superclass constructor found...
                     }
                  }
               }
               //当前构造方法加了@AutoWired注解
               if (ann != null) {
                  //整个类中如果有一个required为true的构造方法,那就不能有其他的加了@Autowired的构造方法
                  if (requiredConstructor != null) {
                     throw new BeanCreationException(beanName,
                           "Invalid autowire-marked constructor: " + candidate +
                           ". Found constructor with 'required' Autowired annotation already: " +
                           requiredConstructor);
                  }
                  boolean required = determineRequiredStatus(ann);
                  //required为true
                  if (required) {
                     //如果已经有@AutoWired注解标注的构造方法,则抛错
                     if (!candidates.isEmpty()) {
                        throw new BeanCreationException(beanName,
                              "Invalid autowire-marked constructors: " + candidates +
                              ". Found constructor with 'required' Autowired annotation: " +
                              candidate);
                     }
                     //记录唯一一个required为true的构造方法
                     requiredConstructor = candidate;
                  }
                  //记录所有加了@AutoWired的构造方法,不管required为true还是false
                  //如果默认无参构造方法上也加了@Autowired注解,那么也会加到candidates中
                  candidates.add(candidate);
               }
               //如果没有被@AutoWired注解标记,并且是无参的,则赋值给defaultConstructor
               else if (candidate.getParameterCount() == 0) {
                  //记录唯一一个无参的构造方法
                  defaultConstructor = candidate;
               }
               //从以上代码可以看出,一个类中要么只能有一个required=true的构造方法,要么只能有一个或多个required=false的构造方法
            }
            //循环完所有的构造方法
            //1.candidates要么为空,也就是没有被@Autowired标记的构造方法
            //2.candidates中只有一个required=true的构造方法
            //3.candidates中是所有required=false的构造方法

            //如果candidates不为空,那么就是有@Autowired标记的构造方法
            if (!candidates.isEmpty()) {
               // Add default constructor to list of optional constructors, as fallback.
               //如果不存在一个required=true的构造方法,那么candidates中都是required=false的构造方法
               if (requiredConstructor == null) {
                  //如果存在无参构造方法将无参构造方法放到candidates中
                  if (defaultConstructor != null) {
                     candidates.add(defaultConstructor);
                  }
                  else if (candidates.size() == 1 && logger.isInfoEnabled()) {
                     logger.info("Inconsistent constructor declaration on bean with name '" + beanName +
                           "': single autowire-marked constructor flagged as optional - " +
                           "this constructor is effectively required since there is no " +
                           "default constructor to fall back to: " + candidates.get(0));
                  }
               }
               //1.如果只存在一个required=true的构造方法,那么只有这一个是合格的
               //2.如果有多个required=false的构造方法,那么所有的required=false的构造方法都是合格的
               //此时如果有无参构造方法,那么所有required=false和无参构造方法都是合格的
               candidateConstructors = candidates.toArray(new Constructor<?>[0]);
            }
            // 如果没有加了@AutoWired注解的构造方法,并且类中只有一个构造方法,并且该构造方法是有参的,这个构造方法也是合格的
            else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
               candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
            }
            // primaryConstructor 不用管kotlin
            else if (nonSyntheticConstructors == 2 && primaryConstructor != null &&
                  defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
               candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
            }
            // primaryConstructor 不用管kotlin
            else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
               candidateConstructors = new Constructor<?>[] {primaryConstructor};
            }
            else {
               // 如果有多个有参、并且没有添加@AutoWired的构造方法,是返回空的
               candidateConstructors = new Constructor<?>[0];
            }
            this.candidateConstructorsCache.put(beanClass, candidateConstructors);
         }
      }
   }
   return (candidateConstructors.length > 0 ? candidateConstructors : null);
}

        可以得出一个结论:Autowired注解的required属性默认为true,一个类中要么只能有一个required=true的构造方法,要么只能有一个或多个required=false的构造方法,没有标注Autowired的方法可以与他们混合存在。

六、带参实例化

        这里需要对构造函数参数进行解析和推断,从而决定调用哪个构造函数,即通过构造函数参数值去匹配构造函数,其源码和注释,以及逻辑总结如下:

public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
      @Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
    //实例化一个beanWrapperImpl类对象
   BeanWrapperImpl bw = new BeanWrapperImpl();
    //初始化bw,这里的BeanFactory来自于AbstractAutowireCapableBeanFactory
   this.beanFactory.initBeanWrapper(bw);
 
    
   Constructor<?> constructorToUse = null;
   ArgumentsHolder argsHolderToUse = null;
   Object[] argsToUse = null;
 
    //explicitArgs不为空,说明用户指定了构造方法的参数,直接拿来使用
   if (explicitArgs != null) {
      argsToUse = explicitArgs;
   }
   else {
      Object[] argsToResolve = null;
      synchronized (mbd.constructorArgumentLock) {
            //尝试从mbd的缓存中拿取构造方法
         constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
            //构造方法不为空并且构造方法已经解析 
         if (constructorToUse != null && mbd.constructorArgumentsResolved) {
            // Found a cached constructor...
            //直接从mbd缓存中拿取构造方法的参数
            argsToUse = mbd.resolvedConstructorArguments;
            if (argsToUse == null) {
                //如果没有拿到构造方法的参数,就获取缓存中的配置文件的参数
               argsToResolve = mbd.preparedConstructorArguments;
            }
         }
      }
      if (argsToResolve != null) {
            //正确拿到配置文件的参数之后,对参数进行解析,最后生成构造方法的参数
         argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
      }
   }
 
    //如果没有拿到构造方法,就说明没有bean进行过解析,需要去关联对应的bean的构造器
   if (constructorToUse == null || argsToUse == null) {
      // Take specified constructors, if any.
        //获取传入的构造器
      Constructor<?>[] candidates = chosenCtors;
        //如果构造器不为空
      if (candidates == null) {
                //获取bean的类型
         Class<?> beanClass = mbd.getBeanClass();
         try {
            //判断是否允许非公开访问,如果允许就获取所有的构造方法,如果不允许就获取public的构造方法
            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);
         }
      }
 
        //如果只有一个构造方法并且,指定参数为空,并且配置文件里面没有构造方法的参数值
      if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
        //获取唯一的构造方法
         Constructor<?> uniqueCandidate = candidates[0];
        //判断这个构造方法的参数个数为0,这个构造方式 就是默认的构造方法
         if (uniqueCandidate.getParameterCount() == 0) {
            synchronized (mbd.constructorArgumentLock) {
                            //记录到mbd的缓存中去
               mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
               mbd.constructorArgumentsResolved = true;
               mbd.resolvedConstructorArguments = EMPTY_ARGS;
            }
            //初始化bean, 并且设置到bw(bean 的包装对象)中去
            bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
            return bw;
         }
      }
 
 
      // Need to resolve the constructor.
        //这里判断了是否是自动导入的
      boolean autowiring = (chosenCtors != null ||
            mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.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);
      }
 
        //对构造方法进行排序,public的排在前面,参数多的排在前面
      AutowireUtils.sortConstructors(candidates);
      int minTypeDiffWeight = Integer.MAX_VALUE;
      Set<Constructor<?>> ambiguousConstructors = null;
      LinkedList<UnsatisfiedDependencyException> causes = null;
 
        //逐一遍历所有的构造方法
      for (Constructor<?> candidate : candidates) {
        //获取构造方法的参数类型
         Class<?>[] paramTypes = candidate.getParameterTypes();
 
            //这里的判断构造方法和构造方法参数 都不是空,又由于之前对构造方法做了排序。所以在使用的参数的个数已经大于当前构造方法的参数个数的时候,实际上已经取到了想要的构造方法。
         if (constructorToUse != null && argsToUse != 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,
                     getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
            }
            catch (UnsatisfiedDependencyException ex) {
               if (logger.isTraceEnabled()) {
                  logger.trace("Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
               }
               // Swallow and try next constructor.
               if (causes == null) {
                  causes = new LinkedList<>();
               }
               causes.add(ex);
              continue;
 
            }
         }
         else {
            // Explicit arguments given -> arguments length must match exactly.
            //用户指定了构造方法的参数时,直接用获取到的参数类型数量与用户传参数量比较,不等于直接跳过当前的构造方法
            if (paramTypes.length != explicitArgs.length) {
               continue;
            }
            argsHolder = new ArgumentsHolder(explicitArgs);
         }
 
            //isLenientConstructorResolution()判断策略是否宽松
            //宽松策略下,使用spring构造的参数数组的类型和获取到的构造方法的参数类型进行对比。
            //严格策略下,还需要检查能否将构造方法的参数复制到对应的属性中
            //会返回一个数值,作为构造方法和参数的差异值
         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<>();
               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 != null) {
         argsHolderToUse.storeCache(mbd, constructorToUse);
      }
   }
 
    //用上面得到的构造器和参数来反射创建bean实例,并放到BeanWrapperImpl对象中然后返回
   Assert.state(argsToUse != null, "Unresolved constructor arguments");
   bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
   return bw;
}

        这个方法的代码量很大,逻辑也比较复杂。我们将逻辑简单拆分,整理成以下几个方面:

1. 构造方法参数值的确定

        1)根据explicitArgs参数判断。

        如果参入的参数explicitArgs不为空,就可以直接确定下参数,因为explicitArgs参数是在调用Bean的时候用户指定的,在BeanFactory类中有这样一个方法:Object getBean(String name, Object... args)

        在获取bean的时候,用户不但可以指定bean的名称还可以指定bean所对应类的构造方法或者工厂方法的参数,主要用于静态工厂方法的调用,这里则是需要给定完全匹配的参数,所以,可以判定explicitArgs不为空,就是构造方法的参数就是它。

        2)缓存中获取

        除此之外,确定参数的办法如果之前已经分析过,构造方法参数已经有记录在缓存中,那么便可以直接拿来使用。但是这里缓存的参数可以是最终的类型也可能是初始的类型。例如:构造方法需要的参数是int类型的1,但是原始参数可能是String类型的“1”,那么即使从缓存中获取到了参数,也需要经过类型转换器来保证与构造方法的参数类型一致。

        3)配置文件获取

        在前两个方法都没法获取到参数的时候,就只能开始新一轮的分析。

从配置文件中获取配置到构造方法的信息开始,经过之前的分析,spring中的配置文件的信息会被转换成通用的BeanDefinition实例,也就是参数mbd,通过调用mbd.getConstructorArgumentValues()来获取配置的构造函数信息。拿到配置中的信息便可以获取到每个参数对应得值。

        4)通过依赖注入获取

        这里涉及到依赖的解析了,在后面文章属性注入详细讲解。

2.构造方法的确定

        经过第一个步之后确定了构造方法的参数,接下来就是要根据构造方法的参数来找到对应的构造方法,匹配的方法就是根据参数的个数对比,在匹配之前需要对构造方法按照public构造方法优先、参数数量降序排列、非public构造方法参数降序排列。这样可以在遍历的情况下迅速的判断出构造方法参数个数是否符合条件。

        由于在配置文件中并不是唯一限制使用参数位置索引的方式去创建,还同时支持指定参数名进行设定参数值的情况,如<constructor-arg name="aa">,这种情况下就需要先确定构造方法中的参数名。

        获取参数名可以用两种方式,一种是通用注解的方式直接获取,另一种就是使用Spring中提供的工具类ParameterNameDiscoverer来获取。构造方法、参数名、参数类型、参数值确定之后却可以确定构造方法。

3.根据参数类型转换对应参数的类型。

4.构造函数不确定性验证

        有的时候根据之前的筛选并无法直接确定需要的构造方法,最后根据匹配度做一次验证

5.根据实例化策略以及得到的构造方法参数对bean进行实例化。

七、无参实例化

        这个逻辑就比较简单了,其对应的方法为SimpleInstantiationStrategy#instatance,通过class对象获取参数个数为0的构造方法来实例化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值