以代码流程方式探索Spring源码(七)--Bean实例化1--getBean--createBean

入口:refresh()中的finishBeanFactoryInitialization(beanFactory);

在此方法中,Spring完成了其初始化过程中的核心:Bean的实例化,在Bean实例化的过程中,顺便完成了一些核心功能,IOC和AOP等。同时,研究spring对Bean的实例化过程,能发现spring是如何提供高扩展性的,为我们自己扩展spring提供示例和方法。
在这里插入图片描述
首先设置类型转换器,先跳过一些准备方法,只关注核心流程。从方法的名字上我们也能看出来,这个方法是要实例化单例的Bean。
在这里插入图片描述
在该方法中,先从beanFactory的beanDefinitionNames中取到所有的beanDefiniton的beanName,用来循环处理。在之前进行标签解析后生成beanDefiniton后,在注册阶段我们知道会有两个容器,一个存放所有的beanName,一个是存放beanName和beanDefinition对应关系的map。

有一个步骤是将父类beanDefinition中的属性拷贝到子类beanDefiniton中,从这一点看出,spring容器中的bean实例化后都是健全的,子类中包含了父类中有的东西,而不是用的时候再去父类取。

有一个分叉是会判断该正在实例化的bean是不是FactoryBean,对于是否不同的结果会走不同的实例化分支,我们暂时先关注通常的bean的实例化,至于factoryBean的实例化后续在看。

我们看到最后还会对生成的bean实例进行一个判断,对具体实例是SmartInitializingSingleton的bean执行对应的后置处理,暂时忽略。

让我们进入getBean()方法!!!
在这里插入图片描述

getBean():bean实例化的真正入口

直接进入劳模do方法
在这里插入图片描述
先尝试从缓存中取。在从缓存中取之前还有一个transformBeanName的操作,这个方法主要是处理beanName前面有&的情况。
在这里插入图片描述
从这段代码可以看出,spring中有着三级缓存,这三级缓存的使用的容器分别为:
1、一级缓存singletonObjects,存储的是bean实例化完成后的对象。
2、二级缓存earlySingletonObjects,存储的是bean还在实例化过程中的对象,其实就是堆内存有了,属性还没有DI依赖注入。
3、三级缓存singletonFactories,存放的是可生成bean的ObjectFactory,有一个getObject方法可以获得bean。

逻辑:先从一级缓存拿,拿到了就直接返回,拿不到就去二级缓存拿,取到了直接返回,取不到就去三级缓存拿对应的ObjectFactory,去三级缓存拿还有一个前置条件是beanFactroy允许bean的提前暴露。如果取到的ObjectFactory不为空,则执行对应的getObject()方法得到实例对象,并升级到二级缓存,同时将三级缓存中的内容移除。那二级缓存到一级缓存的升级是什么时候做的呢?看代码猜就知道是在bean的实例化完成的时候。
在这里插入图片描述
在这里插入图片描述
如果缓存中取到了实例,执行getObjectForBeanInstance()方法,该方法主要是针对FactoryBean类型的beanInstance进行处理,如果不是FactoryBean类型的就会直接返回。这个方法暂时搁置,后续来讨论。继续走主流程。
在这里插入图片描述
缓存中取不到走正常初始化流程。如果bean的scope是prototype类型的,检查是否有循环依赖的情况,如果有,报异常。
在这里插入图片描述
判断有没有父容器,如果有父容器并且子容器没有该bean的beanDefinition,交给父容器去实例化。
在这里插入图片描述
为实例化的bean打个标志
在这里插入图片描述
这个地方有个注意点是使用了双重验证。在我们自己的项目中若有需要可以这样使用。
在这里插入图片描述
这个地方的两个容器:一个map,一个set。set中存放spring容器实例化的单例bean的beanName。回归主流程。
在这里插入图片描述
在标记该bean实例化后,进行实例化:首先进行父子beanDefinition的合并,然后获取该beanDefinition的dependsOn属性,得到该bean实例化的前置bean需求。若依赖bean不为空,则循环去实例化。就是调用对应bean的getBean()方法。
在这里插入图片描述
接下里就根据bean的scope属性产生分支:
1、单例bean的实例化
2、prototype类型bean的实例化
3、自定义scope的bean的实例化
在这里插入图片描述

单例Bean的实例化

在这里插入图片描述
跟进getSingleton()方法,探索creatBean()的准备工作。
1、尝试下缓存
2、执行beforeSingletonCreation(beanName);在before方法中,将beanName存放进了singletonsCurrentlyInCreation容器中,这是一个set,存放所有正在实例化的bean的beanName。
3、调用真正的执行逻辑,就是外部的creatBean()方法。
4、执行afterSingletonCreation(beanName);在after方法中,将beanName从singletonsCurrentlyInCreation中移除。
5、加缓存,之前我们说的从二级缓存升级到一级缓存的操作就是在这里做的。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

createBean()准备进入内核了

直接进入do方法

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

进入do方法后,会有一个createBeanInstance方法

instanceWrapper = createBeanInstance(beanName, mbd, args);

在其中有四类:
1、实例化factoryMethod方法对应的实例。
2、实例化带有@Autowired注解的有参构造函数。
3、实例化没有@Autowired注解的有参构造函数。
4、实例化无参构造函数。

预知后事如何,且听下回分解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值