- instantiateUsingFactoryMethod相关的重要流程总结
-
- instantiateUsingFactoryMethod大致流程
- createArgumentArray大致流程
- 要点
- 重载同名参数个数相同报错
- 一个参数类型多个同类型注入对象报错
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
的内部检查的:
或者这样也可以:
反正你得有区别就行了。一个工厂方法就可以涉及那么多知识点,很多细节也没讲,不是我懒,是因为涉及太深了,会晕的,等把整个流程讲完了再说细节吧。
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。