Spring中Bean实例创建过程
Posted 踩踩踩从踩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中Bean实例创建过程相关的知识,希望对你有一定的参考价值。
Spring中Bean定义加载过程解析_踩踩踩从踩的博客-CSDN博客
前言
本篇文章之前的文章在解析了spring中bean定义的解析及加载,以及 整个spring框架上的ioc的流程,本篇文章会说到一个重要的概念就是beanfactory ,我们面试时一般会问到spring,而spring离不开的就是ioc容器而ioc容器最重要的概念就是beanfactory接口,因为他是暴露给外面使用的方法,所有的实例创建 都会离不开 这个东西。本篇文章会继续解析spring框架,搞清楚ApplicationContext实例化Bean的过程,这个过程中涉及的核心类,楚IOC容器提供的扩展点有哪些,学会扩展,IOC容器这里使用的设计模式,不同创建方式的bean的创建过程 。
实例创建流程
在spring中bean实例的创建是怎么样的,如何实现都是从下面进行深入。
- 实例化bean创建的流程,先确定创建Bean的入口是不是在getBean方法 是在那里的?
ApplicationContext context = new GenericXmlApplicationContext ( "classpath:/application.xml" ); context . getBean ( "lad" );
这个入口 是利用 context去获取bean的方式,而所有的bean 当然不是采用这种方式去获取bean的。
- 在什么时候就开始了Bean的初始化?单例Bean能不能提前初始化好?
- Spring中支持的bean实例创建方式有几种?分别如何配置的,如何来获取Bean实例的?
![](https://image.cha138.com/20221211/7d9fd22188434a1b9a3c4cb524a08373.jpg)
其实创建bean实例的方式有四种。 包括构造方式 工厂方法 指定工厂方法
其实还有一种方式 Factorybean的方式,在使用时 可以 创建 适用在一些外部的组件的集成,是非常好用的。
![](https://image.cha138.com/20221211/7800726126d24f078a993a7e1e832bff.jpg)
在applicationcontext中 初始化bean实例, 判断 bean定义的类型 是否可以混合 ,参数是否达到,通过环境嵌套解析出来。
最后预实例化bean。
![](https://image.cha138.com/20221211/7dc9e555b6af4328b9bc7720270f594c.jpg)
![](https://image.cha138.com/20221211/95d52492dc554850b8debe9545daabf3.jpg)
这里就判断是不是factorybean ,对于factorybean 的方式,带有前缀的。
![](https://image.cha138.com/20221211/d640ec4ad63d4c848c2b06a2dabcdd30.jpg)
针对别名的情况,通过 transformedbeanName方法 就可以获取到 beanName,最终判断。
![](https://image.cha138.com/20221211/6b99d0fb83fc4c9c93ee562d3766f8dc.jpg)
继续dogetbean中 首先从单例Bean中获取
- 单例bean不直接返回,当前的bean有可能是工厂bean,Object需要从工厂bean中获取
- 构造时的循坏依赖的检查
![](https://image.cha138.com/20221211/ae51b0e5c9cd4fbf873f0494f9f1ff07.jpg)
- 判断是否有父工厂,父工厂不为空,本地又不包含该bean定义,从父工厂中获取
![](https://image.cha138.com/20221211/abb10bd1543c4edab1232b683a79b38c.jpg)
- 如果不仅仅是做类型检查,记录该bean已经被创建了
![](https://image.cha138.com/20221211/b7ff0643f5154c55b74456c7c86c947d.jpg)
![](https://image.cha138.com/20221211/f41cb5552448475bb92563d5222fa605.jpg)
- Scope的处理:单例、原型、其他 创建bean实例
- 在 单例 原型 和其他都会调用 getobjectforbeaninstance 获取bean实例。仍然进行一次工厂bean处理
![](https://image.cha138.com/20221211/f90ae694e99e48059e8d45bc09097679.jpg)
- 多例bean的循环依赖的检查处理,并记录
多例Bean的处理
不做存放
循环依赖的检查与记录释放 记录存放的类型 ThreadLocal Scope Bean的获取 存放在Scope中 Scope接口的定义与实现,策略模式应用 SimpleThreadScope存放在ThreadLocal- 最后怎么创建bean 所有的都通过 createbean方法。
![](https://image.cha138.com/20221211/3e40a015338c434b9d4664c5b94c4107.jpg)
![](https://image.cha138.com/20221211/b6a29cdc10bd4ffca9079ad327f42006.jpg)
交给postprocess,应用bean定义的处理。InstantiationAwareBeanPostProcessor
适配器类 InstantiationAwareBeanPostProcessorAdapter 适用点: CGLIB ,来完成实例创建,可以避免创建两个实例。 AbstractAutowireCapableBeanFactory#doCreateBean ,MergedBeanDefinitionPostProcessor的处理,混合处理bean父子类型 急切地缓存单例,以便能够解析循环引用,即使是由生命周期接口触发的,如 BeanFactoryAwares。![](https://image.cha138.com/20221211/9929c39332064976888462041d68d0d2.jpg)
包括属性的判断 初始化 的处理。
解决构造函数的循环依赖。
AbstractAutowireCapableBeanFactory#createBeanInstance![](https://image.cha138.com/20221211/1646b98988844c37b0bc7d8590b220da.jpg)
这里面的逻辑 使用最简单的无参构造函数
工厂 方法 静态工厂方法 等等 创建 具体的实例的方式。
提前准备单例到beanfacotry 到bean.
包括beanfacotrypostprocessor 、beanpostprocessor
beandefinitionregirsterpostprocessor.
针对不同范围的bean的创建模式,单例 多例 scope. 这里 针对的![](https://image.cha138.com/20221211/53fccf92c37d441cb6591bfc58e26b74.jpg)
根据不同的 session 或者request创建一个bean的方式。
对于不同的bean是不同的创建的。
然后在进去的createbean方法 进去的 docreatebean 这里面 有 个缓存 实例先 移除掉
AbstractAutowireCapableBeanFactory #createBean(String, RootBeanDefinition, Object[])看着往里面走, 包括判断 什么 bean类型
AbstractAutowireCapableBeanFactory #doCreateBean AbstractAutowireCapableBeanFactory #createBeanInstance 这在源代码中继续下去看。![](https://image.cha138.com/20221211/78d89ecc4aec46b0899146e5ba407035.jpg)
单例bean,并不是原生的bean,做了很多扩展,暴露的对象,实例化bean对象。
初始化动作之前,属性填充 ,这里 populatebean 就是做的这个操作,
![](https://image.cha138.com/20221211/cd37e846e98a4871803b645481dd86de.jpg)
这里涉及到 依赖注入的东西。
以及 这里 做的 初始化前 做的 涉及到 aop 的前置增强。
初始化方法,这也是经过了前置准备操作,才开始的 初始化 方法
![](https://image.cha138.com/20221211/6027de082fa94beba721806c4002186d.jpg)
这里 涉及到 三个接口 包括 initiazingbean 以及 销毁的disposablebean 接口的
关于bean的生命周期会用到的接口。
属性给完过后。 这在之前 分析Scheduled 任务都会遇到的。 一些
spring源码深入理解 (一): 定时任务-自定义注解及任务及同一时间多任务执行_踩踩踩从踩的博客-CSDN博客 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition AbstractAutowireCapableBeanFactory #populateBean AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition) AbstractBeanFactory#registerDisposableBeanIfNecessary 然后就是后置增强![](https://image.cha138.com/20221211/a8af28032ab140148a030844eb2594a5.jpg)
![](https://image.cha138.com/20221211/69468aa610974bfbba9e5f934197efa8.jpg)
![](https://image.cha138.com/20221211/1ae617b5f80c4b8abfa5d5515c1b3ae4.jpg)
接口 也就是容器关闭后 对工厂的销毁方法。
然后接下来继续说说 createbeaninstance 方法创建bean实例
首先 获取bean的类型。
这里创建 bean实例的时候,这里就开始 根据参数判断 调用那个方式进行创建bean.
包括 bean定义中,还会根据 参数 args时去判断。
根据beanname的class 去判断到底是走那条路
以上是关于Spring中Bean实例创建过程的主要内容,如果未能解决你的问题,请参考以下文章
Spring IOC 容器源码分析 - 创建单例 bean 的过程