| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> spring bean创建过程源码分析(上) -> 正文阅读 |
|
[Java知识库]spring bean创建过程源码分析(上) |
大家好,我是@zzyang(小卓),一个热爱技术的90后。这篇文章主要是带大家了解一下spring bean的生命周期,对spring bean的创建过程源码分析。由于篇幅有限,这里说的都是主干流程,至于一些细节和旁支我都注释和圈出来了,有兴趣自己翻源码,如果有问题、质疑或者想交流探讨技术,可联系我,我们一起探讨技术。 本文是基于spring源码的5.1版本 一、bean的获取阶段 为什么先讲获取。因为spring源码中是先从ioc容器中获取对象,获取不到再创建的。所以这里先从doGetBean方法入手。 ? ?先根据getSingleton方法去获取对象 ,这里就牵扯出三级缓存解决循环依赖的问题.。 三级解决循环引用的问题 * 第一级缓存 singletonFactories ,这getObject的时候会去对bean创建一个代理对象 * 第二级缓存 earlySingletonObjects ,这里是存储早期对象 * 第三级缓存 singletonObjects ,成熟的,彻彻底底可用的实例 如果出现循环依赖的问题,这里就会获取到bean,只不过这个bean还没有被初始化,仅仅只是实例化出来的而已,如果需要被代理,这里其实也会被代理 假设没获取到,那么此时往下走else,尝试从父容器中获取bean ?二、bean的创建 父容器也没有,就要自己去创建这个对象,在创建之前合并BeanDefinition 和 注册依赖的bean,@DependsOn注解就是在这个阶段发挥作用的 ?接下来就是对bean的作用返回进行判断,从这里可以看出,其实spring对于bean的作用范围中的单例和多例其实是采用硬编码的方式来进行完成的,其余的bean的作用范围,比如在web环境中的bean作用域session、springcloud环境中的@RefreshScope注解等都是通过扩展org.springframework.beans.factory.config.Scope的实现来完成的。大家有兴趣可以看看SessionScope和RefreshScope这两个实现类。 ? ?补充一点,肯定会有人好奇,我的代码明明没有动过,我的Controller一直在那,怎么做到的一个session一个Controller,其实原理很简单,就是你看见的Controller其实是个代理对象,每次调用的时候都会根据session的不同去重新创建一个新的真正的Controller对象去调用,这里涉及到spring aop的知识,有机会我们再讲。 ? 接着我们顺着创建单例bean继续往下看,把创建单例bean的重要的每个环节都看一遍,从这我们就开始深入bean的生命周期源码阶段。从createBean方法开始 a. bean class 的加载阶段 ?因为可能是通过xml文件来声明bean的,所以要把bean class加载一下 b. bean实例化之前阶段 这个阶段主要是回调所有的InstantiationAwareBeanPostProcessor对象的postProcessBeforeInstantiation方法,这个阶段如果有返回对象,直接不走下面的生命周期了(因为返回值不为null,直接return了),所以一般没有人这么玩。 BeanPostProcessor组件体系 InstantiationAwareBeanPostProcessor,这个接口是BeanPostProcessor的子类,BeanPostProcessor接口及其衍生的接口(接下来我称为BeanPostProcessor组件)是bean生命周期中一个非常核心的类体系,因为spring bean在创建过程中不同的阶段都会回调BeanPostProcessor组件的方法,这样就可以达到扩展的目的。因为只要你自己实现了BeanPostProcessor组件,就可以在生命周期的不同阶段可以对你的bean进行不同的操作,达到自己的目的。比如说阿里开源的dubbo中@DubboReference注解(2.7.7版本推出的注解,取代@Reference注解,功能没有什么变化)在整合spring的过程中主要是通过ReferenceAnnotationBeanPostProcessor来实现的,这个接口就是BeanPostProcessor的实现。说实话,bean的生命周期一大部分都是通过BeanPostProcessor组件来完成扩展的。 我们继续往下看 ?进入resolveBeforeInstantiation方法 ?进入applyBeanPostProcessorsBeforeInstantiation方法 ? c . bean的实例化阶段 这个阶段是根据你的class对象,来创建一个实例对象出来。 进入doCreateBean方法 ?进入createBeanInstance方法,对象就在这个方法创建的 ?@Bean的构建方式、构造器注入创建对象的方式,这两个创建的细节就不研究了 ?通过带构造参数的实例化构造方法来实例化我们就不看了。那么就进入instantiateBean方法 ?从这里可以看出,不论怎么走,都是通过getInstantiationStrategy方法获取实例化对象的策略然后调用instantiate来实例化对象。点进getInstantiationStrategy方法会发现其实是获取的CglibSubclassingInstantiationStrategy,那么我们就进入instantiate方法 ?这里我们可以看出,其实是获得了class的默认构造器,然后调用BeanUtils.instantiateClass(constructorToUse)来实例化对象,这是这内部就是简单的反射调用构造器创建对象。就不点进去了。 其实从这里我们可以看出,其实spring在创建对象实例的时候,最简单的方式其实就是通过反射直接通过调用的构造方法进行实例化。其实spring对象的实例化还有其他的方式,比如我上面图片标注的@Bean的构建方式、构造器注入创建对象的方式都不是走这。 在后面就是对创建创建出来的对象包装成BeanWrapper对象,直接返回。至此,bean的对象就被实例化出来了。 d. bean 的实例化之后阶段 接着往下看。 ?这是一个很重要的一步,主要是为了解决循环依赖的,跟文章最前面说的解决循环依赖是能够相呼应上的。 接下来看populateBean方法? ?看看,这里就是继续回调BeanPostProcessor组件体系的方法,所以回调完就表明spring bean的创建阶段完成。至于这个阶段为什么叫spring的bean的实例化之后阶段,你可以看看回调的方法的名字,翻译过来就是后置处理在bean实例化之后,所以叫这个阶段。 这个方法回调完之后下面代码就是bean生命周期中又一个核心的阶段,那就是属性赋值阶段,什么@Autowired依赖注入之类的其实就是在下面代码给你完成的。但是你有没有发现,postProcessAfterInstantiation如果这个方法返回false,下面的代码就不会执行了,所以一般扩展也没有返回false的,没人这么玩。其实你可以发现,spring在bean的创建过程中提供了非常多的可扩展点,你可以在每个阶段改变bean的创建行为,虽然可能没有人去这么做,但是spring依然提供了这些点。其实这也是读源码的有趣的地方,你可以看见各种扩展点,自己就可以去使用扩展点,进行各种骚操作。 总结: 我们把这篇文章总结一下,最开始说讲了bean的获取,自己的容器获取不到就会从父容器获取,如果都没获取到就会自己创建。说创建之前,简单的说明了spring是如何通过三级缓存解决循环依赖的问题。创建的时候会根据bean的作用域不同,进行了不同的创建。接下来我们选择了深入单例bean的创建源码,进入了bean创建的生命周期阶段,bean class 的加载,bean的实例化阶段,详细分为实例化之前阶段、实例化阶段、实例化之后阶段,顺便插入了对BeanPostProcessor组件体系的讲解。至于spring bean的生命周期的其它阶段,比如属性赋值阶段,初始化阶段,我会再写一篇文章来讲述剩下的阶段。预知后事如何,就请听下回分解吧。谢谢大家。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 5:23:25- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |