我们来讲一下Bean的实例化过程。这篇文章中,暂时不对Bean循环依赖的情况进行分析,因为比较复杂,会放在后面单独的文章中进行分析。
准备工作看下面这条语句AnnotationConfigApplicationContext类的refresh方法开始分析,从下面这条语句开始:
从官方的注释可以看出,这里是用来完成所有非懒加载的bean的实例化过程。
我们先写一个简单的bean用于进行测试,其中的Dao也是一个交给spring管理的bean。spring会扫描到这个类,并添加到beanDefinitionMap和BeanDefinitionNames中:
看一下finishBeanFactoryInitialization中的代码:
这个方法中,前面都是在做一些准备工作,直到最后执beanFactory的preInstantiateSingletons方法,才开始准备执行非懒加载的bean的实例化过程。先看preInstantiateSingletons方法的前半段:
首先从beanDefinitionNames的List中拿到所有的beanName,进行遍历。之前讲过DefaultListableBeanFactory内部缓存了一个beanDefinitionMap的Map,和这个beanDefinitionNames的List,从这也可以看出,通过适当的冗余可以一定程度上减少编码中的工作量。
在对bean进行初始化前包含3个条件:不能为抽象类、单例bean、以及非懒加载。非常好理解不再多说,重点说明一下通过isFactoryBean方法判断bean是否Factorybean。Factorybean是一个比较特殊的bean,并且受spring容器管理,看一下接口定义:
如果一个类实现了FactoryBean接口,那个spring容器中会存在两个对象,一个是getObject方法返回的对象,另一个是当前FactoryBean对象本身,并且用&添加在beanName前进行区分。举个例子:
测试:
结果:
com.hydra.dao.TestDao@fbd1f6com.hydra.factorybean.MyFactoryBean@1ce24091
对于FactoryBean的获取,要在beanName前加上一个前缀&,然后会先判断是否是SmartFactoryBean并且isEagerInit为true,如果是才调用getBean方法进行初始化。此处内容略过,直接看重要的getBean方法:
此处为空方法,继续调用doGetBean方法,从这开始为实例化bean的核心流程。
实例化bean为了方便分析,我们将类与方法按照调用顺讯进行编号,方便后面解析流程的分析。
1、AbstractBeanFactory 的 doGetBean方法和以前一样,非重点的内容直接在代码中用注释解释。
在创建bean前,首先调用了DefaultSingletonBeanRegistry的getSingleton方法,也就是说spring在初始化一个bean前先去尝试获取一次,判断这个对象是否已经被实例化好了,如果已经存在就直接拿过来用。进入getSingleton方法,核心代码:
看一下singletonObjects的定义:
这里提前剧透一下,这个Map就是用于存放实例化好的单例bean,并且从狭义上来说,可以说这个singletonObjects就是spring容器,并且它使用了ConcurrentHashMap,来保证并发操作的安全性。
因为我们的bean还处于创建阶段,那么这一次是肯定不能从Map获取到实例的,那么接着向下运行,看一下调用的createBean方法。
2、AbstractAutowireCapableBeanFactory 的 createBean方法前面做了很长的铺垫工作,但还是没有创建bean,创建bean的工作被交给了doCreateBean方法完成。
3、AbstractAutowireCapableBeanFactory 的 doCreateBean方法这里面做了三个比较重要的工作:
①、调用createBeanInstance方法创建bean实例②、调用populateBean进行属性的填充,依赖注入就是在这里完成③、调用initializeBean,执行各种后置处理器,执行各种回调函数我们按照顺序,先接着讲①中创建bean势力的过程,等这个过程完了再回头分析属性填充和回调方法。
4、AbstractAutowireCapableBeanFactory 的 createBeanInstance方法如果bean拥有多个构造方法的话,会根据参数去判断具体使用哪一个,具体内容比较复杂,准备以后放在一篇单独的文章中进行分析。如果只有无参构造方法或不写构造方法的话,都会默认使用无参构造方法进行实例化,这里暂时只对这种情况进行分析。
5、AbstractAutowireCapableBeanFactory 的 instantiateBean方法这里通过getInstantiationStrategy得到类的实例化策略,默认情况下是得到一个反射的实例化策略。然后调用instantiate方法进行实例化。
6、SimpleInstantiationStrategy 的 instantiate方法instantiateClass方法中,通过反射创建对象:
运行到这,实例化的过程就完成了,但是目前属性还没有注入,回到开头我们举的那个例子,其中还有一个Dao没有被注入,下一篇文章,我们接下来分析属性的注入。
到此这篇关于Spring源码解析 Bean的实例化的文章就介绍到这了,更多相关Spring Bean实例化内容请搜索七叶笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持七叶笔记!