bean的创建(五)第三部分 bean工厂方法参数的解析
准备好一系列参数之后,开始参数类型的转换,方法参数的对应。
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工厂方法参数的解析的更多相关文章
- java之设计模式工厂三兄弟之工厂方法模式
[学习难度:★★☆☆☆,使用频率:★★★★★] 简单工厂模式虽然简单,但存在一个很严重的问题.当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码 ...
- Spring 源码(17)Spring Bean的创建过程(8)Bean的初始化
知识回顾 Bean的创建过程会经历getBean,doGetBean,createBean,doCreateBean,然后Bean的创建又会经历实例化,属性填充,初始化. 在实例化createInst ...
- 设计模式(三)——Java工厂方法模式
工厂方法模式 1 看一个新的需求 披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪 pizza.北京的胡椒 pizza 或者是伦敦的奶酪 pizza.伦敦的胡椒 pizza. ...
- Spring 工厂方法创建Bean 学习(三)
1, 静态工厂方法创建Bean 调用静态工厂方法创建 Bean是将对象创建的过程封装到静态方法中. 当客户端需要对象时, 只需要简单地调用静态方法, 而不同关心创建对象的细节. 要声明通过静态方法创建 ...
- Spring学习笔记之 Spring IOC容器(一)之 实例化容器,创建JavaBean对象,控制Bean实例化,setter方式注入,依赖属性的注入,自动装配功能实现自动属性注入
本节主要内容: 1.实例化Spring容器示例 2.利用Spring容器创建JavaBean对象 3.如何控制Bean实例化 4.利用Spring实现bean属性sett ...
- 0003 - 基于xml的Spring Bean 的创建过程
一.目录 前言 创建 Bean 容器 加载 Bean 定义 创建 Bean Spring Bean 创建过程中的设计模式 总结 二.前言 2.1 Spring 使用配置 ApplicationCont ...
- Spring IoC bean 的创建(上)
前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 容 ...
- Spring学习--静态工厂方法、实例工厂方法创建 Bean
通过调用静态工厂方法创建 bean: 调用静态工厂方法创建 bean 是将对象创建的过程封装到静态方法中 , 当客户端需要对象时 , 只需要简单地调用静态方法 , 而不需要关心创建对象的细节. 要声明 ...
- Spring 源码(11)Spring Bean 的创建过程(2)
Spring Bean 的创建过程介绍了FactoryBean 的创建方式,那么接下来介绍不是FactoryBean的创建方式,在创建过程中,又会分为单例的Bean的创建,原型类型的Bean的创建等. ...
随机推荐
- 基于 Kong 和 Kubernetes 的 WebApi 多版本解决方案
前言 大家好,很久没有写博客了,最近半年也是比较的忙,所以给关注我的粉丝们道个歉.去年和朱永光大哥聊的时候提了一下我们的这个方案,他说让我有空写篇博客讲一下,之前是非常的忙,所以这次趁着有些时间就写一 ...
- .NET Core IdentityServer4实战 第Ⅳ章-集成密码登陆模式
回顾下ClientCredentials模式,在ReSourceApi中定义了我们公开服务,第三方网站想要去访问ReSourceApi则需要在身份验证服务中获取toekn,根据token的内容,硬编码 ...
- laravel中的构造函数依赖注入理解
laravel中的自动依赖注入是非常强大的,刚开始会疑惑为什么只要在构造函数中传入一个强制类型的变量(就是参数有类型限制)过去就行了? 通过查看源码即查阅资料发现其实这其中有一个php技术,就是反射技 ...
- Java web环境的搭建
学习java web 首先得要能够在自己的电脑上配置环境,经查阅资料后了解,需要装java EEEclipse ,即企业版的,还有就是tomcat服务器. 第一步,从网上下载,eclipse 企业版的 ...
- tar命令中的 -C 作用
我用这个命令:tar zcvf chao.tar.gz /chao/* 打包文件的时候,在压缩包里把 /chao/这个路径也打包进去了. [root@yunwei-test chao]# ls / ...
- C# 死锁 Task/AutoResetEvent
与之前<C# 死锁 TaskCompletionSource>类似,还有很多死锁的案例 使用Task异步转同步时,使用不当造成的死锁 private void Task_OnClick(o ...
- mysql中TINYINT的取值范围
在MySQL的数据类型中,Tinyint的取值范围是:带符号的范围是-128到127.无符号的范围是0到255(见官方<MySQL 5.1参考手册>http://dev.mysql.com ...
- SqlHelper(基础)
using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; usin ...
- Jsoup配合 htmlunit 爬取异步加载的网页
加入 jsoup 和 htmlunit 的依赖 <dependency> <groupId>org.jsoup</groupId> <artifactId&g ...
- UVALive 6255:Kingdoms(状压DFS)
题目链接 题意 给出n个王国和n*n的矩阵,mp[i][j] 代表第 i 个王国欠第 j 个王国 mp[i][j] 块钱.如果当前的王国处于负债状态,那么这个王国就会被消除,和它相连的王国的债务都会被 ...