该文章基于《Spring源码深度解析》撰写,感谢郝佳老师的奉献
如果想要弄清Bean创建到使用的一整套流程实际上非常复杂,bean的处理可以是Spring的核心之一:
- 首先需要对标签属性进行处理
- 进行Bean的加载
- 进行BeanFactory的加载
下面按顺序进行介绍对标签属性的处理,这一部分的的处理很复杂(以后用空再慢慢补充,现在仅给出逻辑步骤):
- 首先委托BeanDefinitionDelegate类的parseBeanDefinationElement方法对元素进行解析,返回BenaDefinitionHolder类型的实例,此时该实例已经具有了配置文件中的各种属性
- 如果默认标签还有自定义属性,还需要对自定义属性进行解析
- 上面2步就已经完成了解析,接下来的注册操作委托给了BeanDefinitionReaderUtils的registerBeanDefinition方法
- 最后发出响应事件,通知监听器,告知该bean的标签已经解析完成
就下来介绍bean的加载,该部分更加复杂,以后有机会再介绍具体细节,以后用空再慢慢补充,现在仅给出逻辑步骤):
- 转换对应beanName(实际上就是消除别名依赖)
- 尝试从缓存中加载单例(使用了双锁检查(DCL))
- bean的实例化(在Sping中一般通过反射机制实例化bean,如果存在缓存,那么直接返回缓存,否则依赖于ObjectFactory进行创建(同时可以处理处理循环依赖的问题),并且在创建时调用实例化前、后的后处理器,同时进行动态AOP织入,属性的注入,在前面的事情都完成之后Spring将通过init-method对bean进行自定义初始化方法调用,并且将BeanDefinition转换为BeanWrapper返回)
- 原型模式(prototype)的依赖检查(原型模式无法处理循环依赖,因为Spring不会缓存prototype作用域的bean,所以也无法提前曝光ObjectFactory)
- 检测parentFactory
- 将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition
- 寻找依赖
- 针对不同的scope进行bean的创建(默认singleton,prototype,reqeuest)
-
类型转换
因为这东西确实不好讲,我直接给一张我整理的图:
下面主要解释一下Spring中如何处理循环依赖,分为三种情况:
构造器循环依赖:抛出异常
setter循环依赖:通过提前暴露的ObjectFactory进行创建
prototype的循环依赖:直接报错