准备好一系列参数之后,开始参数类型的转换,方法参数的对应。
ConstructorResolver.createArgumentArray 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); ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
//用于储存可以使用的参数
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);
// Try to find matching constructor argument value, either indexed or generic.
//尝试从indexed和generic集合中寻找符合条件的参数,indexed可以根据参数下标获取,没有指定下标的可以更具参数名或者参数的类型去获取。
ConstructorArgumentValues.ValueHolder valueHolder =
resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
//如果没有找到,使用通过的值,什么都没有指定的,就指定了一个值的参数
if (valueHolder == null && !autowiring) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
if (valueHolder != null) {
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
//如果找了对应的参数,那么保存到usedValueHolders集合中
usedValueHolders.add(valueHolder);
//获取原始的值,这个值可能是某个bean,还没有进行类型转换
Object originalValue = valueHolder.getValue();
Object convertedValue;
//如果已经进行了转换的,存入预备参数中
if (valueHolder.isConverted()) {
convertedValue = valueHolder.getConvertedValue();
args.preparedArguments[paramIndex] = convertedValue;
}
else {
//如果没有被转换过,那么就进行类型转换
ConstructorArgumentValues.ValueHolder sourceHolder =
(ConstructorArgumentValues.ValueHolder) valueHolder.getSource();
//获取最原始的值,比如一个BeanRuntimeReference。
Object sourceValue = sourceHolder.getValue();
try {
convertedValue = converter.convertIfNecessary(originalValue, paramType,
MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex));
// TODO re-enable once race condition has been found (SPR-7423)
/*
//如果最原始的值和经过解析后的参数一致,那么就将最原始的ValueHolder的已转换的值设置成类型转换后的值,表示这个转化后的值就是通过当前valueholder的值转化后的值,并把转化后的值设置都预备参数数组中,值得注意的是,这段代码被注释掉了
if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {
// Either a converted value or still the original one: store converted value.
sourceHolder.setConvertedValue(convertedValue);
args.preparedArguments[paramIndex] = convertedValue;
}
else {
*/
//标记参数已经被解析,并将最原始的值设置给了预备参数集合
args.resolveNecessary = true;
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;
} //如果没有找到匹配的参数,那么就进行自动装配,自动装配通过参数类型去BeanFactory去寻找符合类型的bean或者是用@Value注解修饰的
else {
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, paramIndex, paramType,
"Ambiguous " + methodType + " argument types - " +
"did you specify the correct bean references as " + methodType + " arguments?");
}
try {
MethodParameter param = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);
//自动装配,这里和对preparedArguments参数的自动装配是一样的解析方法。
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);
}
}
}
//注册依赖,记录当前beanName依赖的bean的name,用于检测循环依赖
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;
}

bean的创建(五)第三部分 bean工厂方法参数的解析的更多相关文章

  1. java之设计模式工厂三兄弟之工厂方法模式

    [学习难度:★★☆☆☆,使用频率:★★★★★] 简单工厂模式虽然简单,但存在一个很严重的问题.当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码 ...

  2. Spring 源码(17)Spring Bean的创建过程(8)Bean的初始化

    知识回顾 Bean的创建过程会经历getBean,doGetBean,createBean,doCreateBean,然后Bean的创建又会经历实例化,属性填充,初始化. 在实例化createInst ...

  3. 设计模式(三)——Java工厂方法模式

    工厂方法模式 1 看一个新的需求 披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪 pizza.北京的胡椒 pizza 或者是伦敦的奶酪 pizza.伦敦的胡椒 pizza. ...

  4. Spring 工厂方法创建Bean 学习(三)

    1, 静态工厂方法创建Bean 调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节. 要声明通过静态方法创建 ...

  5. Spring学习笔记之 Spring IOC容器(一)之 实例化容器,创建JavaBean对象,控制Bean实例化,setter方式注入,依赖属性的注入,自动装配功能实现自动属性注入

    本节主要内容:       1.实例化Spring容器示例    2.利用Spring容器创建JavaBean对象    3.如何控制Bean实例化    4.利用Spring实现bean属性sett ...

  6. 0003 - 基于xml的Spring Bean 的创建过程

    一.目录 前言 创建 Bean 容器 加载 Bean 定义 创建 Bean Spring Bean 创建过程中的设计模式 总结 二.前言 2.1 Spring 使用配置 ApplicationCont ...

  7. Spring IoC bean 的创建(上)

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...

  8. Spring学习--静态工厂方法、实例工厂方法创建 Bean

    通过调用静态工厂方法创建 bean: 调用静态工厂方法创建 bean 是将对象创建的过程封装到静态方法中 , 当客户端需要对象时 , 只需要简单地调用静态方法 , 而不需要关心创建对象的细节. 要声明 ...

  9. Spring 源码(11)Spring Bean 的创建过程(2)

    Spring Bean 的创建过程介绍了FactoryBean 的创建方式,那么接下来介绍不是FactoryBean的创建方式,在创建过程中,又会分为单例的Bean的创建,原型类型的Bean的创建等. ...

随机推荐

  1. Jenkins持续部署-自动生成版本号

    目录 Jenkins持续部署-自动生成版本号 目录 前言 目的 详细流程 获取SVN Reversion 获取需求号 设置编译前读取版本号 总结 参考文献 Jenkins持续部署-自动生成版本号 目录 ...

  2. RestTemplate使用不当引发的问题分析

    背景 系统: SpringBoot开发的Web应用: ORM: JPA(Hibernate) 接口功能简述: 根据实体类ID到数据库中查询实体信息,然后使用RestTemplate调用外部系统接口获取 ...

  3. eclipse 工具在工作中实用方法

    不断更新记录工作中用到的实用技巧 1.快捷方式管理多个工作空间 参数: -showlocation 设置eclipse顶部显示工作空间位置 -data 文件位置 设置打开的工作空间位置 创建eclip ...

  4. RocketMQ(6)---发送普通消息(三种方式)

    发送普通消息(三种方式) RocketMQ 发送普通消息有三种实现方式:可靠同步发送.可靠异步发送.单向(Oneway)发送. 注意 :顺序消息只支持可靠同步发送. GitHub地址: https:/ ...

  5. mysql数据库在linux下的导出和导入及每天的备份

    mysql数据库的导出,导入 1. 导出数据库为sql文件 mysqldump 数据库名 -uroot -p > xxx.sql 导出数据表结构和数据 eg.   mysqldump cloud ...

  6. 搭建本地pip源

    搭建本地的pip源 开发环境部署机器的时候, 每次从网上下载pip包会很慢, 将需要的包和相关依赖下载到本地, 搭建一个本地源服务器. 基本都是安装多个包, 推荐使用文件的方式, 文件内容格式, 可以 ...

  7. c语言:链表

    1.链表概述: 链表是一种数据结构,它采用动态分配存储单元方式.它能够有效地节省存储空间(同数组比较). 由于链表中的节点是一个结构体类型,并且结点中有一个成员用于指向下一个结点.所以定义作为结点的格 ...

  8. Android 蓝牙开发(2)——低功耗蓝牙

    低功耗蓝牙官方文档 本文章是参考官网,然后加入自己实践中的理解完成!没有看上一篇的读者,可以先阅读一下前一篇,这是一个系列. 官网地址:https://developer.android.com/gu ...

  9. HDU 1828:Picture(扫描线+线段树 矩形周长并)

    题目链接 题意 给出n个矩形,求周长并. 思路 学了区间并,比较容易想到周长并. 我是对x方向和y方向分别做两次扫描线.应该记录一个pre变量,记录上一次扫描的时候的长度,对于每次遇到扫描线统计答案的 ...

  10. scrapy基础知识之下载中间件使用案例:

    1. 创建middlewares.py文件. Scrapy代理IP.Uesr-Agent的切换都是通过DOWNLOADER_MIDDLEWARES进行控制,我们在settings.py同级目录下创建m ...