Spring源码--Bean的加载

Posted jazon@

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码--Bean的加载相关的知识,希望对你有一定的参考价值。

bean的加载在AbstractBeanFactory的doGetBean中

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException 

doGetBean的过程

1.转换对应的beanName
传入的name可能是别名,也可能是FactoryBean,所以需要进行一系列的解析
2.尝试从缓存中加载单例
单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。这里只是尝试加载,首先从缓存中加载,如果加载不成功,则尝试从signletonFactories中记载。为了解决循环依赖问题,在不等bean创建完成,就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory。
3.bean的实例化
如果从缓存中得到了bean的原始状态,则需要对bean进行实例化,因为缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。比如我们获取到工厂bean,其次我们是想要其getObject返回的bean。而getObjectForBeanInstance就是完成这个工作。
4.原型模式的依赖检查
5.检测parentBeanFactory
如果缓存找不到且存在parentBeanFactory且当前beanFactory没有beanName对应的BeanDefinition则转到父类工厂去加载。
6.将GernericBeanDefinition转换为RootBeanDefinition
因为一开始读取的信息都是存在GenericBeanDefinition的,但是所有的bean后续处理都是针对RootBeanDefinition的,所以这里需要进行一个转换,转换时,如果父类bean不为空的话,则会一并合并父类的属性。
7.寻找依赖
初始化bean时,首先初始化这个bean对应的依赖
8.针对不同的scope进行bean的创建
spring中存在不同的scope,其中默认是singleton,但是还存在其他配置,如prototyoe,request等,在这步,Spring会根据不同的配置进行不同的初始化策略。
9.类型转换
如果requireType和返回的bean类型不一致,Spring会使用转换器进行转换。

缓存中获取单例bean

1.尝试从singletonObjects获取bean
2.尝试从earlySingletonObjects里面获取
3.尝试从singletonFactories获取ObjectFactory,获取得到调用其getObject方法来创建bean,并放到earlySingletonObjects中,并且从singletonFacotories里面remove吊这个ObjectFactory。

从bean的实例中获取对象

1.对FactroyBeaan正确性的验证
2.对非FactoryBean不做任何处理
3,对bean进行转换
4.将从FactoryBean中解析bean的工作委托给getObjectFromFactoryBean

获取单例

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) 

1.检查缓存是否以及加载过
2.若没有加载,则记录beanName的正在加载状态
3.加载单例前记录加载状态,即beforeSingletonCreation
4.通过调用参数传入的ObjectFactory的getObject方法实例化Bean
5.加载单例后的处理方法调用,afterSingletionCreation移除正在加载状态
6.将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态,如二级,三级缓存等。对应的方法为protected void addSingleton(String beanName, Object singletonObject);

准备创建bean

1.根据设置的class属性或者根据className来解析Class
2.对override属性进行标记及验证
3.应用初始化前的后处理器,解析指定bean是否存在初始化前的短路操作,InstantiationAwareBeanPostProcessor在实例化前可以根据beanClass,beanName返回bean,此bean将替代后续的创建。

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) 
    return bean;

4.创建bean

Spring的循环依赖

1.构造器循环依赖,会报错
2.setter循环依赖,spring会解决
3.prototype无法解决

创建bean

1.如果是单例则需要首先清楚缓存
2.实例化bean,将BeanDefinition转换为BeanWrapper。
3.MergedBeanDefinitionPostProcessor的应用,beanDefinition合并后的处理,Autowired注解正式通过此方法实现诸如类型的预解析。
4.提前暴露ObjectFactory解决循环依赖问题
5.属性填充populateBean
6.从二级缓存将有循环依赖的bean获取到
7.注册DisposableBean
8.完成创建并返回

populdateBean的处理流程

1.InstantiationAwareBeanPostProcessor处理器的postProcessAfterInstantiation函数的应用,可以控制程序是否继续属性填充。
2.根据注入类型(byName/byType)提取依赖的bean,并同意存入PropertyValues中。
3.应用InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues方法,对属性获取完毕填充前对属性的再次处理。
4.将所有PropertyValues中的属性填充至BeanWrapper中。

初始化bean

1.調用aware方法
2.BeanPostProcess的前置处理
3.激活自定义的init方法
4.BeanPostProcessor的后置处理

注册DisposableBean

1.destroy-method
2.DestructionAwareBeanPostProcessor

以上是关于Spring源码--Bean的加载的主要内容,如果未能解决你的问题,请参考以下文章

Spring读源码系列04----bean的加载---上

Spring源码分析

Spring源码--Bean的加载

Spring源码--Bean的加载

Spring源码--Bean的加载

spring源码-bean之加载-2