Spring 获取单例流程 (三)
读完这篇文章你将会收获到
``
Spring
`何时将
`bean
`` 加入到第三级缓存和第一级缓存中``
Spring
`何时回调各种
`Aware
`接口、
`BeanPostProcessor
`、
`InitializingBean
`` 等
相关文章
Spring 循环依赖 (公众号内查看(同时发布无法获取到链接))
概述
上两篇文章介绍了 ``getBean
`` 前面的流程,今天最后的收尾,把后面的流程继续一起学习下
源码分析
如果我们要创建的 ``bean
`` 是一个单例,
删减了部分不重要的代码,我们大致来看看其流程
获取同步锁,然后判断第一级缓存是否已经存在这个 ``
bean
`` 了如果不存在则将 ``
beanName
`加入到
`singletonsCurrentlyInCreation
`` 中,代表它正在创建中然后调用参数的 ``
ObjectFactory
`的
`getObject
`方法获得一个
`bean
``最后将其从 ``
singletonsCurrentlyInCreation
`` 中移除、代表其已经创建完成了最后将其加入到第一级缓存中、从第二级和第三级缓存中移除掉
全篇完结.终 !!!
其实真正的秘密藏身在参数的 ``ObjectFactory
` 中,从上面的流程中可以宏观的知道
`Spring
` 创建
`bean
`` 的一个流程
现在我们在看看参数的 ``ObjectFactory
`` 究竟干啥子了
干活的还是 ``do
`` 开头的大佬
上面的流程大致就是
``
createBeanInstance
`这个方法根据你的配置以及你的
`bean
`的情况选择出一种创建
`bean
`的方法、可能是工厂方法、可能是某个构造函数、可能是默认的构造函数。这里包含了当一个构造函数的参数是另一个
`bean
`的时候、它会通过
`getBean
`的方法获取这个参数的
`bean
``
然后将创建好的 ``
bean
`` 加入到第三级缓存中,默认设置我们是允许循环依赖的
``
populateBean
`方法就是我们填充属性了、如果你依赖的其他
`Spring
`的其他
`bean
`是通过这种方式注入的话(
`autowireByName
`autowireByType
`)、就是在这一步注入的了,他获取其他
`bean
`也是通过
`getBean
``的方式获取
``
initializeBean
`则是调用我们的各种回调接口、
`Aware
`类型的、
`BeanPostProcessor
`、
`InitializingBean
``、自定义初始化函数
其实整体的流程就差不多了
总结
根据参数中的 ``
name
`找出对应的
`beanName
`、无论这个
`name
`是别名或者是一个
`factoryBean
`的
`beanName
``查看缓存中是否包含这个 ``
beanName
`` 对象
- 先从一级缓存 ``singletonObjects
`` 中看看有没有
- 然后从二级缓存 ``earlySingletonObjects
``
- 都没有的话再从三级缓存 ``singletonFactories
`` 中看看有没有
如果缓存中有 ``
bean
`、那么我们还是需要处理一下这个
`bean
``
- 如果 ``Spring
` 缓存中返回的
`bean
` 是
`factoryBean
` 、而用户也想要的是一个
`beanFactory
` (参数
`name
` 中的前缀是
`&
`` )、那么我们直接返回
- 如果 ``Spring
` 缓存中返回的
`bean
` 是普通的
`bean
`、而用户也想要的是一个普通的
`bean
`` 、那么就直接返回
- 如果 ``Spring
` 缓存中返回的
`bean
` 是一个
`factoryBean
` 、而用户想要的是一个普通的
`bean
` 、那么我们就要从
`factoryBean
` 中获取这个
`bean
``
- 而从 ``factoryBean
` 中获取这个
`bean
` 的过程中、需要调用到前置处理、后置处理和我们常用的接口回调
`BeanPostProcessor
``
如果缓存中没有 ``
bean
`、则判断是否是
`prototype
`` 类型并且循环依赖如果没有则尝试能否在父容器中找到该 ``
bean
``如果父容器也没有则获取该 ``
beanName
`对应的
`beanDefinition
`找出其依赖的
`beanName
``判断该 ``
beanName
`与 依赖的
`beanName
`是否循环依赖、没有则注册其依赖关系并调用
`getBean
`方法去创建依赖的
`beanName
``将 ``
beanName
`加入到
`singletonsCurrentlyInCreation
`` 中根据指定 bean 使用对应的策略创建新的实例、如工厂方法、构造函数、创建一个不完整的 bean
将创建好的 bean 加入到第三级缓存中
进行属性填充、进行各种接口回调
最后将其从 ``
singletonsCurrentlyInCreation
`` 中移除、代表其已经创建完成了最后将其加入到第一级缓存中、从第二级和第三级缓存中移除掉
返回 ``
bean
`` 给调用方
其实总体的流程还是不算复杂把、我们也可以从中收获到一些东西。其实我们最关心也是面试最常问的一个问题就是、Spring 如何解决循环依赖的问题、感兴趣的可以看看这篇文章公众号内的 ``Spring 循环依赖
`` 这篇文章
版权声明: 本文为 InfoQ 作者【CoderLi】的原创文章。
原文链接:【http://xie.infoq.cn/article/3c561280f5e0693415e7a8add】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论