从根儿上学习spring 十一 之run方法启动第四段(5)

图15-AbstractAutowireCapableBeanFactory#doCreateBean方法

我们接着讲doCreateBean方法,之前对循环依赖做了些解释,我们接着往下看populateBean(beanName, mbd, instanceWrapper)方法

图15-572行

这行就是调用populateBean(beanName, mbd, instanceWrapper)方法对实例化好的bean对象进行属性注入,也就是处理我们经常使用的@autowired或者@resource这些注解。我们看下该方法的代码

图16-AbstractAutowireCapableBeanFactory#populateBean方法

图16-1277到1286行

这几行没什么好说的,做了个简单的空值校验,如果bean实例为空但beanDefinition却定义了bean属性的value值则报错,否则直接返回。

图16-1291到1303行

这几行的目的只有一个,就是调用后置处理器InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法对bean属性进行设值。如果该方法返回了false说明bean属性已设置完毕不需要populateBean方法后续继续对bean进行属性设置。continueWithPropertyPopulation属性就是来判断是否需要后续继续对bean的属性进行设置。对于具体有哪些后置处理器做了什么不是我们当前的重点,大家只需要知道这里spring为我们提供了一个扩展点即可。这个后置处理器我们前面也说过,这里就不赘述了。

图17-AbstractAutowireCapableBeanFactory#populateBean方法

图17-1309到1322行

这几行的功能主要是获取bean实例中的属性,然后根据beanDefinition定义的注入类型判断是否根据name注入或者根据类型注入去获取每个属性对应的bean实例。根据name注入也就是通过beanName去spring容器获取该属性的bean实例,根据类型注入是根据属性class类型到spring容器中获取该属性的bean实例。最后将获取到的属性bean实例根据属性名作为key放到newPvs变量中,为后面对属性设值做准备。

图18-AbstractAutowireCapableBeanFactory#populateBean方法

图18这段逻辑主要做了两件事,

1331-1342:判断当前spring容器是否有InstantiationAwareBeanPostProcessor后置处理器的存在,如果有则执行其postProcessPropertyValues方法,该方法允许我们在对bean设置属性前对属性的值进行修改,也就是修改pvs或者直接替换pvs;

1343-1345:对bean的属性进行检查,检查必填属性是否为空。一共有4中检查模式都定义在AbstractBeanDefinition类里,分别是DEPENDENCY_CHECK_NONE-不检查,DEPENDENCY_CHECK_OBJECTS-检查引用类型的属性,DEPENDENCY_CHECK_SIMPLE-检查基本类型的属性,DEPENDENCY_CHECK_ALL-所有类型的属性都检查。

1348-1350:通过反射对属性进行设值,完成属性注入。

讲到这AbstractAutowireCapableBeanFactory#populateBean方法也就讲完了,接下来我们开始讲图15-AbstractAutowireCapableBeanFactory#doCreateBean方法的initializeBean(beanName, exposedObject, mbd)方法。

图16-AbstractAutowireCapableBeanFactory#initializeBean(Object, RootBeanDefinition)方法

AbstractAutowireCapableBeanFactory#initializeBean(Object, RootBeanDefinition)方法的逻辑相对而言简单了很多,我们从上往下看来捋一下。

图16-1674到1682行

这几行的逻辑就是调用了invokeAwareMethods(beanName, bean)方法,这个方法的逻辑很简单就是判断当前初始化的bean是不是实现了Aware接口,如果实现了该接口那么就判断具体的Aware接口类型,比如是否是BeanNameAware接口,是的话则调用其setBeanName方法等等,这个方法很简单大家自己点进去看下就明白了,我就不赘述了。

图16-1684到1687行

这几行就是调用之前我们说过的一个bean后置处理BeanPostProcessor的postProcessBeforeInitialization方法,该方法的含义是在执行bean的初始化前执行,具体指的是在执行spring的InitializingBean#afterPropertiesSet方法前执行,这个方法我们马上就会说到。

图16-1690行

这行就是判断当前bean是否实现了InitializingBean接口,如果实现了这个接口则调用其afterPropertiesSet方法,这也是spring提供的给我们的扩展,给我们提供自定义初始化bean的能力。

图16-1697到1699行

这几行是调用BeanPostProcessor的postProcessAfterInitialization方法,在bean初始化完成之后提供的一个扩展方法。到这我们的bean就彻底初始化完毕了。

让我们再回到AbstractAutowireCapableBeanFactory#doCreateBean方法的剩余部分。

图17-AbstractAutowireCapableBeanFactory#doCreateBean方法

earlySingletonExposure变量我们之前说过,如果spring容器允许单例循环依赖且当前bean是单例且当前bean正在创建改变量就为true。然后调用getSingleton(beanName, false)方法第二个参数为false表示不允许从单例工厂中获取实例,只能从单例容器singletonObjects或者提前暴露的单例容器earlySingletonObjects中获取实例。

目前虽然bean已经初始化好但目前spring还未将bean实例放入单例容器singletonObjects中,所以在没有出现循环依赖的情况下这里获取到的Object earlySingletonReference变量为空没啥好说的。如果earlySingletonReference不为空说明出现了循环依赖,当前beanName对应的bean提前暴露了一个实例就是earlySingletonReference。

接下来判断exposedObject == bean,这个判断一般都是相对的,因为如果是循环依赖的情况且bean是需要动态代理的,那么在前面getEarlyBeanReference(beanName, mbd, bean)方法执行的时候就会执行动态代理,后面就不会再执行动态代理,这也是为什么这个判断成立的情况下要使用earlySingletonReference给exposedObject赋值的原因。

如果exposedObject不等于bean,说明在initializeBean方法里执行后置处理器时更改了bean的引用,那么提前暴露出去的bean也将失效。这时候如果提前暴露的bean已经被其它bean引用了,那就需要报错。

最后判断当前bean是否需要注册为DisposableBean,注册为DisposableBean的话在容器销毁时会执行其destroy()方法。

感谢大家的观看,希望这些文章可以帮助大家更好理解spring。

相关推荐
乐之者v4 分钟前
leetCode43.字符串相乘
java·数据结构·算法
QQ同步助手4 分钟前
如何正确使用人工智能:开启智慧学习与创新之旅
人工智能·学习·百度
流浪的小新11 分钟前
【AI】人工智能、LLM学习资源汇总
人工智能·学习
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
半盏茶香1 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Evand J2 小时前
LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度
开发语言·matlab
LucianaiB2 小时前
探索CSDN博客数据:使用Python爬虫技术
开发语言·爬虫·python
Ronin3052 小时前
11.vector的介绍及模拟实现
开发语言·c++
计算机学长大白3 小时前
C中设计不允许继承的类的实现方法是什么?
c语言·开发语言
suweijie7683 小时前
SpringCloudAlibaba | Sentinel从基础到进阶
java·大数据·sentinel