Spring 如何选择类构造器
抛出问题:
这样一个类,Spring在实例化的时候会用哪个构造方法,大部分人应该会猜是无参构造方法,可以说是对的,但不完全对
再换一个:
如果是这样呢?
Spring还是会选择无参的,小伙伴可以自行尝试
定位源码
避免有些小伙伴没看过Spring源码,这里从最最开始的源头开始摘录处理
(其实这也是实例化Bean的路径。。)
代表一个方法
org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
然后就到了我们今天需要看的源码了,先来个概览
我们前面都不看,只看一行determineConstructorsFromBeanPostProcessors这个方法。determineConstructorsFromBeanPostProcessors这个方法就是今天的重头戏,他会返回一个 Constructor<?>[],这个就是Spring会选择的构造器数组,返回一个数组?不要紧,Spring会在autowireConstructor里选择一个来进行初始化,怎么选择这就是第二节的内容
Spring怎么判断类有几个构造器
determineConstructorsFromBeanPostProcessors源码分析
看注释应该比较清晰了,大致总结一下:
Spring会首先获取你声明的所有构造函数
然后会循环获取到的所有构造函数,判断有没加@Autowired注解,有加的会放到候选构造函数集合candidates里面去,默认@Autowired为true,check存在多个@Autowired为true的构造函数,有一个@Autowired为true的构造函数的构造函数就会设置为requiredConstructor,如果存在一个参数个数为0的构造函数(也只会有一个,就是无参构造函数),会设置为defaultConstructor
最后判断选择逻辑如下:
如果candidates不为空,在再加上requiredConstructor为null且defaultConstructor不为null,则选用candidates+defaultConstructor,否则则选用candidates
如果声明的只有一个构造函数,且参数个数大于0的,则直接选用返回
如果有两个声明的构造函数,然后primaryConstructor和defaultConstructor都不为null且两个不相等,则两个都作为返回值
如果只有primaryConstructor,且primaryConstructor不为null,则使用他
啥都不满足就是没有即Spring会用他自己的默认的构造函数(其实就是无参构造)
给几个例子
例子一(只有无参):
值得注意的是这种只有无参的,determineConstructorsFromBeanPostProcessors返回null
如果看懂了上面代码就很好理解,Spring为什么这么做呢?因为Spring认为你提供一个无参构造的,相当于没有提供构造函数,Spring会使用自己的无参构造,效果是一致的。
例子二(只有一个有参)
也很好理解,在上面有一个if,如果只有一个有参那么会返回此构造
例子三(结合上面两个,既提供无参又提供有参)
看上面代码,如果提供了两个构造,但是又没加@Autowired,然后又不满足上面第3.3那个if,那么不会选用你提供的这两个,直接返回Null,因为Spring不知道你想选择哪一个
例子四(我们怎么返回多个构造函数让Spring去抉择选用)
其实就是这个方法determineConstructorsFromBeanPostProcessors,怎么返回一个数组
如果能完全看懂上面代码。那么要返回一个[]。就需要如下写了:
其实也很好理解就是如果你要让Spring后面去判断哪个构造函数最适合,你得先用@Autowired来声明哪些个来参与判断,这里值得注意的是required 这个属性必须显示声明,否则默认为true,那就只能有一个构造被 @Autowired标注了,这里也只会返回一个,其实也就是上面的requiredConstructor
看完这些例子,就知道抛出问题的第二个肯定会return null了,不信的话大家可以尝试下,如果return null,那么Spring会利用反射调用无参构造进行Bean的初始化
好,有了多个构造,那么Spring怎么选择哪一个构造进行初始化呢,是选参数多的还是参数少的,或者说是public的呢?这个后面再说
版权声明: 本文为 InfoQ 作者【申屠鹏会】的原创文章。
原文链接:【http://xie.infoq.cn/article/489dba335a4e99c53e25eebd3】。文章转载请联系作者。
评论