本期,边肖将为大家带来《豆定义》的原理。文章内容丰富,从专业角度进行分析和描述。希望你看完这篇文章能有所收获。
一、BeanDefinition浅析
10-1010首先,我来问一个问题:java对象和Spring Bean有什么区别?
这是一个经典的面试问题。什么是java对象?一切都是一个物体。Java中的所有类在创建后都可以被称为对象。SpringBean也是一个java对象,但是SpringBean与JAVA对象是分开的。为什么这么说?因为一个类只能通过new来调用一个对象,但是一个类需要经过一系列的生命周期才能成为Spring Bean。什么生命周期?我以后再说吧!
至少从上面我们可以知道,Spring Bean是一个特殊的Java对象,所以它一定和JAVA对象不一样!
JAVA中的类对象可以描述一个JAVA对象,但是因为SpringBean是一个特殊的Java对象,类对象不能完全描述一个Spring Bean,所以Spring正式开发了一个名为BeanDefinition的类来描述一个Spring Bean!
1. 基本概念了解
BeanDefinition描述了很多事情,大致如下:
Image-20200907164143213它存储了Spring在创建bean过程中需要的所有原材料!
2. 大致结构
提升效率:之春通过反思创造阶级。创建类时,需要一些创建信息,比如类,比如注释信息等。它是预先缓存的,可以在创建bean时直接从缓存中获取,从而提高创建效率。方便修改:当Spring创建一个对象时,所有创建的信息都是由存储在BeanDefinition中的信息创建的,所以我们可以通过修改BeanDefinition中的特定值来改变创建对象的结果!方便扩展:我们可以通过一些特定的接口获取一个类的所有BeanDefinition信息,从而完成一些特定功能的实现!00-1010通过上面的介绍,那么你对BeanDefinition有了一个大概的了解,所以当我们理解整个Spring声明周期的时候,我们需要知道两个概念,BeanFactoryPostProcessor和BeanPostProcessor。当然,这只是为了普及概念,让读者对Spring的申报周期有更深入的了解!
3. 他是干嘛的(Spring构建它的优势)?
我们现在通过上面的理解知道了一件事,那就是Spring会在创建对象之前把类转换成一个BeanDefinition。这时,Spring为我们提供了一个扩展点。在读取了所有的类并将其转换为bean定义后,所有实现BeanFactoryPostProcessor接口的实现类都被回调并传递到工厂对象中,这样用户就可以修改工厂对象内部的属性,例如修改BeanDefinition中的信息,从而操纵最终实例化的bean!
说白了,他在扫描完项目,把Class转换成BeanDefinition之后,就会有进步。
行实例化之前进行接口的回调!
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
方法
三、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
的形式存在!
上述就是小编为大家分享的BeanDefinition的原理是什么了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/133183.html