本文共 22575 字,大约阅读时间需要 75 分钟。
本篇文章是上一篇文章()的延续。在上一篇文章中,我们从战略层面上领略了doCreateBean
方法的全过程。本篇文章,我们就从战术的层面上,详细分析doCreateBean
方法中的一个重要的调用,即createBeanInstance
方法。在本篇文章中,你将看到三种不同的构造 bean 对象的方式。你也会了解到构造 bean 对象的两种策略。如果你对这些内容感兴趣,那么不妨继续往下读。我会在代码进行大量的注解,相信能帮助你理解代码逻辑。好了,其他的就不多说了,进入正题吧。
本节,我们一起来来分析一下本篇文章的主角createBeanInstance
方法。按照惯例,我们还是先分析一下方法的大致脉络,然后我们再按照这个脉络去分析一些重要的调用。So. Let`s go → ↓
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 | protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { Class beanClass = resolveBeanClass(mbd, beanName); /* * 检测类的访问权限。默认情况下,对于非 public 的类,是允许访问的。 * 若禁止访问,这里会抛出异常 */ if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName()); } /* * 如果工厂方法不为空,则通过工厂方法构建 bean 对象。这种构建 bean 的方式 * 就不深入分析了,有兴趣的朋友可以自己去看一下。 */ if (mbd.getFactoryMethodName() != null) { // 通过“工厂方法”的方式构建 bean 对象 return instantiateUsingFactoryMethod(beanName, mbd, args); } /* * 当多次构建同一个 bean 时,可以使用此处的快捷路径,即无需再次推断应该使用哪种方式构造实例, * 以提高效率。比如在多次构建同一个 prototype 类型的 bean 时,就可以走此处的捷径。 * 这里的 resolved 和 mbd.constructorArgumentsResolved 将会在 bean 第一次实例 * 化的过程中被设置,在后面的源码中会分析到,先继续往下看。 */ boolean resolved = false; boolean autowireNecessary = false; if (args == null) { synchronized (mbd.constructorArgumentLock) { if (mbd.resolvedConstructorOrFactoryMethod != null) { resolved = true; autowireNecessary = mbd.constructorArgumentsResolved; } } } if (resolved) { if (autowireNecessary) { // 通过“构造方法自动注入”的方式构造 bean 对象 return autowireConstructor(beanName, mbd, null, null); } else { // 通过“默认构造方法”的方式构造 bean 对象 return instantiateBean(beanName, mbd); } } // 由后置处理器决定返回哪些构造方法,这里不深入分析了 Constructor [] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); /* * 下面的条件分支条件用于判断使用什么方式构造 bean 实例,有两种方式可选 - 构造方法自动 * 注入和默认构造方法。判断的条件由4部分综合而成,如下: * * 条件1:ctors != null -> 后置处理器返回构造方法数组是否为空 * * 条件2:mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR * -> bean 配置中的 autowire 属性是否为 constructor * 条件3:mbd.hasConstructorArgumentValues() * -> constructorArgumentValues 是否存在元素,即 bean 配置文件中 * 是否配置了 |
以上就是 createBeanInstance 方法的源码,不是很长。配合着注释,应该不是很难懂。下面我们来总结一下这个方法的执行流程,如下:
这里有三种构造 bean 对象的方式,如下:
下面我将会分析第2和第3种构造 bean 对象方式的实现源码。至于第1种方式,实现逻辑和第2种方式较为相似。所以就不分析了,大家有兴趣可以自己看一下。
本节,我将会分析构造方法自动注入的实现逻辑。代码逻辑较为复杂,需要大家耐心阅读。代码如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 | protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, Constructor [] ctors, Object[] explicitArgs) { // 创建 ConstructorResolver 对象,并调用其 autowireConstructor 方法 return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);}public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd, Constructor [] chosenCtors, final Object[] explicitArgs) { // 创建 BeanWrapperImpl 对象 BeanWrapperImpl bw = new BeanWrapperImpl(); this.beanFactory.initBeanWrapper(bw); Constructor constructorToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; // 确定参数值列表(argsToUse) if (explicitArgs != null) { argsToUse = explicitArgs; } else { Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { // 获取已解析的构造方法 constructorToUse = (Constructor ) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // 获取已解析的构造方法参数列表 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { // 若 argsToUse 为空,则获取未解析的构造方法参数列表 argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { // 解析参数列表 argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve); } } if (constructorToUse == null) { boolean autowiring = (chosenCtors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR); ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; if (explicitArgs != null) { minNrOfArgs = explicitArgs.length; } else { ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); /* * 确定构造方法参数数量,比如下面的配置: * |
上面的方法逻辑比较复杂,做了不少事情,该方法的核心逻辑是根据参数值类型筛选合适的构造方法。解析出合适的构造方法后,剩下的工作就是构建 bean 对象了,这个工作交给了实例化策略去做。下面罗列一下这个方法的工作流程吧:
由上面的流程可以看得出,通过构造方法自动注入的方式构造 bean 对象的过程还是很复杂的。为了看懂这个流程,我进行了多次调试,算是勉强弄懂大致逻辑。由于时间有限,我并未能详细分析 autowireConstructor 方法及其所调用的一些方法,比如 resolveConstructorArguments、 autowireConstructor 等。关于这些方法,这里只写了个大概,有兴趣的朋友自己去探索吧。
看完了上面冗长的逻辑,本节来看点轻松的吧 - 通过默认构造方法创建 bean 对象。如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 | protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; // if 条件分支里的一大坨是 Java 安全相关的代码,可以忽略,直接看 else 分支 if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged(new PrivilegedAction |
上面就是通过默认构造方法创建 bean 对象的过程,比较简单,就不多说了。最后我们再来看看简单看看通过无参构造方法刚创建 bean 对象的代码(通过 CGLIB 创建 bean 对象的方式就不看了)是怎样的,如下:
123456789101112131415161718192021 | public static |
到这里,终于看到了创建 bean 对象的代码了。在经历层层调用后,我们总算是追到了调用栈的最深处。看到这里,大家可以休息一下了,本文也差不多要结束了。好了,最后再容我多啰嗦一会,往下看。
写到这里,我也算是松了一口气,终于快写完了。这篇文章写起来感觉挺不容易的,原因是 createBeanInstance 及其调用的方法是在太多了,而且很多方法逻辑还是比较复杂的,尤其是 autowireConstructor 中调用的一些方法。autowireConstructor 中调用的方法我基本上都看了一遍,但并非全部都弄懂了,有些方法只是知道个大概。所以,这篇文章写的我挺纠结的,生怕有些地方分析的不对。由于我后续还有很多东西要看,以至于我暂时没法抽出大量的时间去详细阅读 Spring 的源码。所以如果上面的分析有不对的地方,欢迎指正,我会虚心听之。如果这些不对的地方给你造成了困扰,实在很抱歉,抱歉。
好了,本篇文章先到这里。谢谢阅读!
更新时间 | 标题 |
---|---|
2018-05-30 | |
2018-06-01 | |
2018-06-04 | |
2018-06-06 | |
2018-06-08 | |
2018-06-11 | |
2018-06-11 |
更新时间 | 标题 |
---|---|
2018-06-17 | |
2018-06-20 | |
2018-06-20 | |
2018-06-22 |
更新时间 | 标题 |
---|---|
2018-06-29 | |
2018-06-30 |
- 本文链接:
from:
转载地址:http://kjwrf.baihongyu.com/