准备好一系列参数之后,开始参数类型的转换,方法参数的对应。
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. 不用 qlv 格式转换成 mp4 - 优雅的下载腾讯视频(mp4 格式)

    不用 qlv 格式转换成 mp4 - 优雅的下载腾讯视频(mp4 格式) 问题描述: 朋友说离线腾讯视频是 qlv 格式的,只能使用腾讯视频软件打开.让我帮忙想想办法,能不能将 qlv 格式转换成 m ...

  2. spring 5.x 系列第4篇 —— spring AOP (代码配置方式)

    文章目录 一.说明 1.1 项目结构说明 1.2 依赖说明 二.spring aop 2.1 创建待切入接口及其实现类 2.2 创建自定义切面类 2.3 配置切面 2.4 测试切面 2.5 切面执行顺 ...

  3. Programming In Lua 第一章

    1,Lua可以嵌入其他应用程序(如CGILua或IUPLua). 2,lua代码的语句,分号是可以省略的.同一行可以有多条lua语句,最好用分号隔开(当然也可以不隔开) 3,外壳与lua解释器的区别. ...

  4. 基于STM32之UART串口通信协议(二)发送

    一.前言 1.简介 在上一篇UART详解中,已经有了关于UART的详细介绍了,也有关于如何使用STM32CubeMX来配置UART的操作了,而在该篇博客,主要会讲解一下如何实现UART串口的发送功能. ...

  5. OSI参考模型---网络基础篇(1)

    什么是网络 网络就是将分布在不同地理位置,具有独立功能的终端(一切联网的设备都叫终端:例如电脑,手机,智能家电等等联网的设备),通过通信线路(双绞线.光纤.电话线等等)和通信设备(例如:交换机.路由器 ...

  6. Spring3 springMVC添加注解式WebSocket

    Spring3添加注解式WebSocket 推荐升级成spring4以后,spring4已经集成WebSocket. 由于种种原因,项目开发处于快结束的阶段了,升级成spring4不想那么麻烦,但是又 ...

  7. jQuery 文本框 光标 移动到 文字最后

    方法一:调用办法:setCaretToPos(document.getElementById("YOURINPUT"), 4); function setSelectionRang ...

  8. ZigBee入门第一天

    按键查询控制灯的状态 1.宏定义灯和按键 2.按键和灯初始化 3.用if语句消抖的方法,实现按键控制灯的状态 相关寄存器 PxSEL PxDIR #include"ioCC2530.h&qu ...

  9. Windows下通过VNC远程访问Linux服务器,并实现可视化

    前言 最近因部门需要,老大想让我在公司Linux服务器上弄个Oracle,以用作部门测试环境的数据库服务器,经过一番折腾后,成功完成了任务.因公司Linux服务器是无图形界面的,本人接触Linux不多 ...

  10. Linux指令学习

    Linux命令格式:命令名  选项  参数 Linux 刚面世时并没有图形界面,所有的操作全靠命令完成,如 磁盘操作.文件存取.目录操作.进程管理.文件权限 设定等,在职场中,大量的服务器维护工作都是 ...