有道无术,术尚可求也!有术无道,止于术!
1、BeanDefinition浅析
1. 基本概念了解
首先我提出一个问题:一个java对象和一个Spring Bean有什么区别?
java
这是一个经典的面试题,什么是java Object
?万物皆对象,在Java内部全部的类,通过建立以后均可以称之为一个对象,SpringBean也是一个java Object
, 可是Spring Bean是脱离
于JAVA Object的,为何这么说呢?由于一个class要想变成对象只须要new
一下,就可以称之为一个对象,可是一个类要想变成一个Spring Bean就须要通过一系列的生命周期,什么生命周期呢?后面会说到!web
至少从上面的能够知道,Spring Bean是一个特殊的Java Object, 那么他确定有和JAVA Object有不同的地方!面试
Java中 Class对象能够描述一个JAVA Object,可是由于Spring Bean是一个特殊的JAVA Object,因此Class对象不可以完整的描述一个Spring Bean,因此Spring官方单独开发了一个叫作BeanDefinition
的类,来描述一个SpringBean
!spring
2. 大体结构
BeanDefinition
里面描述了不少的东西,大体以下:缓存

它里面存放了Spring建立bean的过程当中所须要的一切原料!微信
3. 他是干吗的(Spring构建它的优点)?
-
提高效率:Spring建立一个类是经过反射建立的,建立类的时候须要一些建立信息,好比Class,好比注解信息等等,事先将这些信息缓存起来,在建立bean的时候可以直接从缓存中获取从而达到提高建立效率的目的。 -
方便修改:spring建立对象的时候,建立的信息所有是经过 BeanDefinition 内存储的信息来建立对象的,因此,咱们能够经过修改BeanDefinition内部特定的值来改变Spring建立对象的结果! -
方便扩展:咱们经过一些特定的接口,能够获取到一个类的全部的BeanDefinition信息,从而完成一些特定功能的实现!
2、Spring生命周期
经过上面的介绍,那么你对
BeanDefinition
有了一大概的认识,那么咱们在了解整个Spring的声明周期的时候,须要了解两个概念BeanFactoryPostProcessor
、BeanPostProcessor
,固然这里只是普及一下概念,是为了可以让读者更加深刻的去理解Spring的声明周期!app
1. 什么是BeanFactoryPostProcessor?
咱们如今经过上面的了解知道了一件事,就是Spring在建立对象以前会把class转换成一个BeanDefinition
, 此时Spring为咱们提供了一个扩展点,他能够在读取彻底部的class转换为 BeanDefinition
以后,回调全部实现了BeanFactoryPostProcessor
接口的实现类,并传入工厂对象,使得使用者可以对工厂对象内部的属性进行修改,例如:对BeanDefinition
内的信息进行修改,以达到操纵最终实例化bean的目的!编辑器
说白了,他会在扫描完项目将Class转换为BeanDefinition
以后在进行实例化以前进行接口的回调!post
2. 什么是BeanPostProcessor?
这个类和上面那个类十分的类似,他有两个方法,两个方法的调用时机也不相同,他会在实例化以后,调用初始化方法以前进行第一次方法回调(postProcessBeforeInitialization),在执行完初始化方法以后又会进行一次回调(postProcessAfterInitialization),每次回调该类都会将当前建立好的bean传递到方法内部,从而让开发者可以自定义的修改当前bean的一些定义!学习
3. Spring生命周期浅析
那么此时,咱们了解了BeanDefinition
、BeanPostProcessor
、BeanFactoryPostProcessor
这三个概念以后,咱们能够尝试着学习一下Spring的生命周期,学习Spring声明周期对掌握Spring源码具备举足轻重的地位!只有了解Spring的声明周期,才可以对后续Spring系列的技术进行一个详尽的源码掌握!
整个Spring的生命周期,以文字描述大概分为如下几个阶段:
-
初始化bean容器,以方便后续的全部的读取的信息的存储! -
初始化内置的class文件转换为bd -
初始化bean工厂,设置一些默认值! -
向BeanFactory内部注册一些本身自己内置的Bean后置处理器 -
执行项目内置的 BeanFactoryPostProcessor
扫描项目将全部的@Bean、@Component....
或者xml配置
等符合Spring读取对应的类解析成BeanDefinition
,存储在容器里面! -
执行咱们自定义的 BeanFactoryPostProcessor
-
注册全部的 BeanPostProcessor
到容器内部! -
初始化国际化资源 -
初始化事件资源 -
实例化class -
按照规则进行属性填充(自动注入) -
回调 BeanPostProcessors.postProcessBeforeInitialization
方法 -
调用bean的初始化方法 -
回调 BeanPostProcessors.postProcessAfterInitialization
方法

3、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
,他在原来的基础上扩展了两个方法:

这两个方法是专门对注解读取的方法!全部注解标识的bean都是这个类型的bean!
I. AnnotatedGenericBeanDefinition

第一种状况是配置类也就是标注了@Configuration
注解的类会被解析成 AnnotatedGenericBeanDefinition
第二种状况是经过@Import
导入的类会被解析成AnnotatedGenericBeanDefinition
II. ConfigurationClassBeanDefinition

经过@Bean
注解导入的类会被解析为ConfigurationClassBeanDefinition
III. ScannedGenericBeanDefinition

经过@Service、@Compent
等方式建立的bean 会以ScannedGenericBeanDefinition
的形式存在!
才疏学浅,若是文章中理解有误,欢迎大佬们私聊指正!欢迎关注做者的公众号,一块儿进步,一块儿学习!
❤️「转发」 和 「在看」 ,是对我最大的支持❤️
本文分享自微信公众号 - JAVA程序狗(javacxg)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。