spring源码学习 resolveConstructorArguments()方法

本文详细分析了Spring框架中ConstructorResolver类的resolveConstructorArguments方法,涉及构造函数参数的解析、类型转换、依赖查找和值的设置,确保构造函数在实例化bean时能正确工作。
摘要由CSDN通过智能技术生成

概述

此方法位于ConstructorResolver类中,用于解析构造函数参数。主要是完成构造函数参数类型的转换等功能。

在spring的xml配置文件中,有时候会配置constructor-arg标签中的内容。有时候,在constructor-arg标签中,不指定参数的名称,而是用参数的下标索引(默认是使用下标索引)。类似于这种情况,构造函数参数需要被解析之后才能使用,resolveConstructorArguments()方法,就是用来解析构造函数的重要方法之一。

resolveConstructorArguments()源码分析

/**
 * 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.
 * 将此bean的构造函数参数解析到resolvedValues对象中。
 * 这可能需要查找其他bean。
 * 此方法还用于处理静态工厂方法的调用
 */
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
      ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {

   TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
   TypeConverter converter = (customConverter != null ? customConverter : bw);
   // ConstructorResolver中有成员变量AbstractAutowireCapableBeanFactory beanFactory
   // 再创建ConstructorResolver对象的时候注入
   BeanDefinitionValueResolver valueResolver =
         new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);

   // cargs来自于mbd.getConstructorArgumentValues()
   int minNrOfArgs = cargs.getArgumentCount();

   // 这里对应的是用下标指定的构造函数的参数
   // entry的key为参数的下标,value为参数的值
   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);
      }
      // 如果参数的下标已经达到了minNrOfArgs的长度,则需要扩大minNrOfArgs
      if (index + 1 > minNrOfArgs) {
         minNrOfArgs = index + 1;
      }
      
      ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
      // 如果属性已经被转换。就直接加入解析完毕的构造函数参数列表
      if (valueHolder.isConverted()) {
         resolvedValues.addIndexedArgumentValue(index, valueHolder);
      }
      else {
         // 如果属性没有被转换,就进入转换流程,转换完成后加入解析完毕的构造函数参数列表
         // valueResolver.resolveValueIfNecessary()方法用于解析属性值,
         // 它接受一个原始的属性值作为参数,并返回解析后的属性值。
         // 该方法在属性注入的过程中被调用,用于处理属性值的解析和转换。
         // 解析后的属性值可以是基本类型、引用类型、集合类型等,根据属性的具体类型进行转换和处理。
         // 解析后的属性值将被用于完成属性注入,将属性值设置到目标对象的相应属性上。
         // valueResolver.resolveValueIfNecessary()还会检查属性值是否包含占位符或表达式,如果包含,则会调用相应的解析器对属性值进行解析
         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;
}

 这里用到了几个类,首先是ConstructorArgumentValues类。

ConstructorArgumentValues的作用?

ConstructorArgumentValues类的作用是存储和管理构造函数参数的值。

ConstructorArgumentValues类是一个用于管理构造函数参数的容器。它提供了一种机制来存储构造函数参数的值,并且可以根据需要进行访问、操作和处理。

ConstructorArgumentValues类的主要作用有以下几个方面:

  1. 存储构造函数参数值:ConstructorArgumentValues类可以用于存储构造函数参数的值。通过该类,可以将构造函数参数的值添加到容器中,并进行管理和维护。

  2. 支持索引和键值访问:ConstructorArgumentValues类提供了多种访问构造函数参数值的方式。可以通过索引或键值来获取指定位置或指定名称的构造函数参数值。

  3. 支持泛型参数值:ConstructorArgumentValues类支持存储和获取构造函数参数的泛型参数值。通过该类,可以获取构造函数参数的泛型参数值,并进行进一步处理。

  4. 支持参数值的类型转换:ConstructorArgumentValues类提供了类型转换的功能。可以将传入的参数值进行类型转换,以匹配目标构造函数参数的类型。

  5. 支持参数值的验证和校验:ConstructorArgumentValues类支持对参数值进行验证和校验。可以对参数值进行合法性检查,以确保参数值的正确性和一致性。

 在ConstructorArgumentValues中,有一个内部类ValueHolder

ValueHolder的作用?

ValueHolder类实现了BeanMetadataElement,BeanMetadataElement是bean元数据接口。bean 元数据是描述 bean 定义和配置信息的对象。BeanMetadataElement接口定义了一些方法,用于获取和设置与 bean 相关的元数据信息。

ValueHolder中有几个重要的成员变量,包括value,type,name,source,converted和convertedValue。这些参数用来描述构造函数的参数的值,类型,参数名称等重要信息。

resolveConstructorArguments()用于解析构造函数参数。它的作用是根据给定的 bean 名称、根 bean 定义、BeanWrapper 对象、构造函数参数值和已解析的参数值,解析并填充构造函数参数。

具体来说,resolveConstructorArguments()方法的主要功能包括:

  1. 根据 bean 名称和root bean 定义获取构造函数元数据。

  2. 根据构造函数元数据和构造函数参数值,解析构造函数参数的索引、类型和值。

  3. 使用 BeanWrapper 对象将解析后的构造函数参数值设置到相应的构造函数参数上。

  4. 如果构造函数参数中包含引用类型的参数,则递归解析引用类型参数的依赖关系。

  5. 将解析后的构造函数参数值存储到已解析的参数值对象中,以便后续使用。

通过执行以上步骤,resolveConstructorArguments()方法能够解析构造函数的参数,并将其填充到相应的构造函数中,以便在实例化 bean 时使用。

 

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值