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
的内部检查的:
或者这样也可以:
反正你得有区别就行了。一个工厂方法就可以涉及那么多知识点,很多细节也没讲,不是我懒,是因为涉及太深了,会晕的,等把整个流程讲完了再说细节吧。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。