专栏首页求道想要学会Spring源码,你必知必会的BeanDefinition原理!

想要学会Spring源码,你必知必会的BeanDefinition原理!

有道无术,术尚可求也!有术无道,止于术!

一、BeanDefinition浅析

1. 基本概念了解

首先我提出一个问题:一个java对象和一个Spring Bean有什么区别?

这是一个经典的面试题,什么是java Object?万物皆对象,在Java内部所有的类,经过创建之后都可以称之为一个对象,SpringBean也是一个java Object, 但是Spring Bean是脱离于JAVA Object的,为什么这么说呢?因为一个class要想变成对象只需要new一下,就能够称之为一个对象,但是一个类要想变成一个Spring Bean就需要经过一系列的生命周期,什么生命周期呢?后面会说到!

至少从上面的可以知道,Spring Bean是一个特殊的Java Object, 那么他肯定有和JAVA Object有不一样的地方!

Java中 Class对象可以描述一个JAVA Object,但是因为Spring Bean是一个特殊的JAVA Object,所以Class对象不能够完整的描述一个Spring Bean,所以Spring官方单独开发了一个叫做BeanDefinition的类,来描述一个SpringBean

2. 大致结构

BeanDefinition里面描述了很多的东西,大致如下:

image-20200907164143213

它里面存放了Spring创建bean的过程中所需要的一切原料!

3. 他是干嘛的(Spring构建它的优势)?

  • 提升效率:Spring创建一个类是通过反射创建的,创建类的时候需要一些创建信息,比如Class,比如注解信息等等,事先将这些信息缓存起来,在创建bean的时候能够直接从缓存中获取从而达到提升创建效率的目的。
  • 方便修改:spring创建对象的时候,创建的信息全部是通过 BeanDefinition 内存储的信息来创建对象的,所以,我们可以通过修改BeanDefinition内部特定的值来改变Spring创建对象的结果!
  • 方便扩展:我们通过一些特定的接口,可以获取到一个类的所有的BeanDefinition信息,从而完成一些特定功能的实现!

二、Spring生命周期

通过上面的介绍,那么你对BeanDefinition有了一大概的认识,那么我们在了解整个Spring的声明周期的时候,需要了解两个概念BeanFactoryPostProcessorBeanPostProcessor,当然这里只是普及一下概念,是为了能够让读者更加深入的去理解Spring的声明周期!

1. 什么是BeanFactoryPostProcessor?

我们现在通过上面的了解知道了一件事,就是Spring在创建对象之前会把class转换成一个BeanDefinition , 此时Spring为我们提供了一个扩展点,他可以在读取完全部的class转换为 BeanDefinition 之后,回调所有实现了BeanFactoryPostProcessor 接口的实现类,并传入工厂对象,使得使用者能够对工厂对象内部的属性进行修改,例如:对BeanDefinition内的信息进行修改,以达到操纵最终实例化bean的目的!

说白了,他会在扫描完项目将Class转换为BeanDefinition 之后在进行实例化之前进行接口的回调!

2. 什么是BeanPostProcessor?

这个类和上面那个类十分的相似,他有两个方法,两个方法的调用时机也不相同,他会在实例化之后,调用初始化方法之前进行第一次方法回调(postProcessBeforeInitialization),在执行完初始化方法之后又会进行一次回调(postProcessAfterInitialization),每次回调该类都会将当前创建好的bean传递到方法内部,从而让开发者能够自定义的修改当前bean的一些定义!

3. Spring生命周期浅析

那么此时,我们了解了BeanDefinitionBeanPostProcessorBeanFactoryPostProcessor这三个概念之后,我们可以尝试着学习一下Spring的生命周期,学习Spring声明周期对掌握Spring源码具有举足轻重的地位!只有了解Spring的声明周期,才能够对后续Spring系列的技术进行一个详尽的源码掌握!

整个Spring的生命周期,以文字描述大概分为以下几个阶段:

  1. 初始化bean容器,以方便后续的所有的读取的信息的存储!
  2. 初始化内置的class文件转换为bd
  3. 初始化bean工厂,设置一些默认值!
  4. 向BeanFactory内部注册一些自己本身内置的Bean后置处理器
  5. 执行项目内置的BeanFactoryPostProcessor扫描项目将所有的@Bean、@Component....或者xml配置等符合Spring读取对应的类解析成 BeanDefinition,存储在容器里面!
  6. 执行我们自定义的 BeanFactoryPostProcessor
  7. 注册所有的BeanPostProcessor到容器内部!
  8. 初始化国际化资源
  9. 初始化事件资源
  10. 实例化class
  11. 按照规则进行属性填充(自动注入)
  12. 回调BeanPostProcessors.postProcessBeforeInitialization方法
  13. 调用bean的初始化方法
  14. 回调BeanPostProcessors.postProcessAfterInitialization方法

123

三、BeanDefinition详解

1. AbstractBeanDefinition

尽管我们可以通过实现BeanDefinition接口创建一个自定义的BeanDefinition,但是你是否发现,自己实现这个接口,想要创建一个BeanDefinition极其复杂里面几十个属性都需要你自己去设置;

Spring官方为了简化这一步骤,提供了一个抽象AbstractBeanDefinition,这个抽象类内部默认实现了BeanDefinition的绝大部分方法,对一些属性进行了默认值的赋值,极大地简化了用户自己实现一个BeanDefinition的难度!

I. GenericBeanDefinition

他是AbstractBeanDefinition的子类,我们通过注解配置的bean以及我们的配置类(除@Bean)外的BeanDefiniton类型都是GenericBeanDefinition类型的!

II. RootBeanDefinition

Spring在启动时会实例化几个初始化的BeanDefinition,这几个BeanDefinition的类型都为RootBeanDefinition,这个包括后续Spring的BeanDefinition会进行一个合并(这都是后话)都是RootBeanDefinition类型的!

我们通过 @Bean创建的BeanDefinition也是RootBeanDefinition类型,当然是属于他的子类(后面会介绍)的!

2. AnnotatedBeanDefinition

这个接口直接继承了BeanDefinition,他在原来的基础上扩展了两个方法:

image-20200907180423084

这两个方法是专门对注解读取的方法!所有注解标识的bean都是这个类型的bean!

I. AnnotatedGenericBeanDefinition

image-20200907180954450

第一种情况是配置类也就是标注了@Configuration注解的类会被解析成 AnnotatedGenericBeanDefinition

第二种情况是通过@Import导入的类会被解析成AnnotatedGenericBeanDefinition

II. ConfigurationClassBeanDefinition

image-20200907182021917

通过@Bean注解导入的类会被解析为ConfigurationClassBeanDefinition

III. ScannedGenericBeanDefinition

image-20200907182139696

通过@Service、@Compent等方式创建的bean 会以ScannedGenericBeanDefinition的形式存在!

才疏学浅,如果文章中理解有误,欢迎大佬们私聊指正!欢迎关注作者的公众号,一起进步,一起学习!

本文分享自微信公众号 - JAVA程序狗(javacxg),作者:皇甫嗷嗷叫

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一个Spring Bean从诞生到逝去的九次人生转折!

    关于Spring生命周期的学习,前面已经写过很多篇文章去不断的探究Spring对一个Bean的创建、管理过程,在整个SpringBean的生命周期中,BeanP...

    止术
  • Spring:没有人比我更懂Java对象的创建!

    一个Spring Bean是Java对象吗?那么一个对象是Spring Bean吗?

    止术
  • 听说你一读Spring源码就懵?我帮你把架子搭好了,你填就行!

    最近断更了一段时间,因为公司比较忙,周五的时候在公司做了一个关于Netty的分享,后续会总结一下分享出来!

    止术
  • IoC容器初始化过程(下)1 BeanDefinition的载入和解析 2 BeanDefinition在IoC容器中的注册

    JavaEdge
  • Spring官网阅读(五)BeanDefinition(下)

    在上篇文章中,我们学习了BeanDefinition的一些属性,其中有以下几个属性:

    程序员DMZ
  • Spring框架源码脉络分析(一):IoC与容器、Bean和BeanDefinition

    IoC:即控制反转机制。在Spring中的实现表现为IoC容器,属于Spring Core模块最核心的部分。

    星如月勿忘初心
  • Spring官网阅读系列(五):BeanDefinition(下)

    在上篇文章中,我们学习了BeanDefinition的一些属性,其中有以下几个属性:

    秃顶的Java程序员
  • Django之路由系统

    Django的路由系统   URL配置其实就是告诉Django项目你执行代码的路径,本质就是路径和调用的视图函数之间的映射关系表。Django通过这个表,可以把...

    新人小试
  • django之urls系统

    Django的urls系统简介 Django 1.11版本 URLConf官方文档:https://docs.djangoproject.com/en/1.11...

    人生不如戏
  • Spring中的@Qualifier注解你会用吗

    本文小胖哥将带你来了解一下Spring中的@Qualifier注解,它解决了哪些问题,以及如何使用它。我们还将了解它与@Primary注解的不同之处。

    码农小胖哥

扫码关注云+社区

领取腾讯云代金券