作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
instantiateUsingFactoryMethod相关的重要流程总结
前面讲了工厂方法实例化的流程,其实还是比较复杂的,很多细节深入下去就有点蒙了,所以先不深入,先了解大致的流程,所以这里先总结下大致做了什么。
instantiateUsingFactoryMethod大致流程

createArgumentArray大致流程

要点
- 有多个有参方法的时候,会进行排序,按
public优先,protected次之,如果修饰符一样,就按照参数的多少排。 - 每一个方法都尝试获取参数装配对象,然后根据方法参数类型的匹配度来判断是否有相同类型的方法,如果有的话是没办法判断用哪个参数的,会报异常。这样就为了选出最合适的方法来进行实例化了。
比较方法是先看参数的类型,也就是转换后对不对,转换后不对那就不行,返回最大差异权重,然后再判断原始类型,比如原始类型是Object,然后转到参数类型xxx的,这样也不行,返回最大差异-512,
最后如果类型全不都正确,就返回最小差异。
//获得差异,越小越好
public int getAssignabilityWeight(Class<?>[] paramTypes) {
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
return Integer.MAX_VALUE;//如果有参数类型不同的话,直接返回最大
}
}
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
return Integer.MAX_VALUE - 512;//有类型和原始参数类型不同的话就-512
}
}
return Integer.MAX_VALUE - 1024;//否则相同就-1024
}
- 遍历候选方法的时候,如果存在显示传参的,就会以显示参数长度为基准,小于该长度的就不处理了,这样可以加快速度,否则每一个都去获取,然后判断差异性就浪费了。
重载同名参数个数相同报错
如果重载了,而且参数都是一个,就会出现不知道用哪个工厂方法啦:

异常信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao' defined in com.ww.config.MyConfig: Ambiguous factory method matches found in bean 'userDao' (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): [public com.ww.pojo.UserDao com.ww.config.MyConfig.userDao(com.ww.pojo.TestBean), protected com.ww.pojo.UserDao com.ww.config.MyConfig.userDao(com.ww.pojo.TestBean2)]
一个参数类型多个同类型注入对象报错
如果这种情况,他也不知道要注入哪个,其实idea已经有提示了,参数名字找不到。

异常信息:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userDao' defined in com.ww.config.MyConfig: Unsatisfied dependency expressed through method 'userDao' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.ww.pojo.TestBean2' available: expected single matching bean but found 2: t1,t2
比如我们可以修改成这样,那就是用t1方法:

注入对象有重复的话,DefaultListableBeanFactory的determineAutowireCandidate方法里会进行判断,然后把对上的方法名所对应的对象注入进来:

当然还有另外的方法比如用Qualifier注解指定哪个方法:

其实内部是在DefaultListableBeanFactory的findAutowireCandidates的判断isAutowireCandidate的内部检查的:

或者这样也可以:

反正你得有区别就行了。一个工厂方法就可以涉及那么多知识点,很多细节也没讲,不是我懒,是因为涉及太深了,会晕的,等把整个流程讲完了再说细节吧。
628

被折叠的 条评论
为什么被折叠?



