概述
此方法位于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类的主要作用有以下几个方面:
存储构造函数参数值:ConstructorArgumentValues类可以用于存储构造函数参数的值。通过该类,可以将构造函数参数的值添加到容器中,并进行管理和维护。
支持索引和键值访问:ConstructorArgumentValues类提供了多种访问构造函数参数值的方式。可以通过索引或键值来获取指定位置或指定名称的构造函数参数值。
支持泛型参数值:ConstructorArgumentValues类支持存储和获取构造函数参数的泛型参数值。通过该类,可以获取构造函数参数的泛型参数值,并进行进一步处理。
支持参数值的类型转换:ConstructorArgumentValues类提供了类型转换的功能。可以将传入的参数值进行类型转换,以匹配目标构造函数参数的类型。
支持参数值的验证和校验:ConstructorArgumentValues类支持对参数值进行验证和校验。可以对参数值进行合法性检查,以确保参数值的正确性和一致性。
在ConstructorArgumentValues中,有一个内部类ValueHolder
ValueHolder的作用?
ValueHolder类实现了BeanMetadataElement,BeanMetadataElement是bean元数据接口。bean 元数据是描述 bean 定义和配置信息的对象。BeanMetadataElement接口定义了一些方法,用于获取和设置与 bean 相关的元数据信息。
ValueHolder中有几个重要的成员变量,包括value,type,name,source,converted和convertedValue。这些参数用来描述构造函数的参数的值,类型,参数名称等重要信息。
resolveConstructorArguments()用于解析构造函数参数。它的作用是根据给定的 bean 名称、根 bean 定义、BeanWrapper 对象、构造函数参数值和已解析的参数值,解析并填充构造函数参数。
具体来说,resolveConstructorArguments()方法的主要功能包括:
-
根据 bean 名称和root bean 定义获取构造函数元数据。
-
根据构造函数元数据和构造函数参数值,解析构造函数参数的索引、类型和值。
-
使用 BeanWrapper 对象将解析后的构造函数参数值设置到相应的构造函数参数上。
-
如果构造函数参数中包含引用类型的参数,则递归解析引用类型参数的依赖关系。
-
将解析后的构造函数参数值存储到已解析的参数值对象中,以便后续使用。
通过执行以上步骤,resolveConstructorArguments()方法能够解析构造函数的参数,并将其填充到相应的构造函数中,以便在实例化 bean 时使用。