22、Spring5.x源码之旅二十二getBean详解八之instantiateUsingFactoryMethod相关总结

  • 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方法:
*
注入对象有重复的话,DefaultListableBeanFactorydetermineAutowireCandidate方法里会进行判断,然后把对上的方法名所对应的对象注入进来:
*
当然还有另外的方法比如用Qualifier注解指定哪个方法:
*
其实内部是在DefaultListableBeanFactoryfindAutowireCandidates的判断isAutowireCandidate的内部检查的:
*
或者这样也可以:
*

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

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。