Spring中BeanDefinition的继承体系

简单说架构

2019-08-05 13:37
关注

Spring中BeanDefinition的继承体系。BeanDefinition Bean定义的本质是什么。

开始

上一篇我们聊到了BeanDefinition,即Bean定义接口,关注到了Bean定义中Bean相关的一系列属性,这一篇,我们不妨从Bean定义接口的几个实现类入手,再去一探Spring Bean。

AbstractBeanDefinition

AbstractBeanDefinition,抽象Bean定义,BeanDefinition的一个抽象实现。该抽象类实现了BeanDefinition接口和Cloneable接口,同时,又继承了BeanMetadataAttributeAccessor类。

BeanMetadataAttributeAccessor,Bean元数据属性访问器,提供访问Bean元数据的一系列方法。元数据就是Bean的一些相关信息,这个我们后续再详细了解。

回到AbstractBeanDefinition,先来看构造方法。

主要有两个构造方法,一个构造方法的参数是构造参数值和属性表,另一个构造方法的参数是原型Bean定义。

要想理解这两个构造方法为什么这么写,就要先理解Bean定义的本质。我们知道,Bean的本质是Java对象,特殊只在于它被Spring所管理。而Bean定义,本质实际是Spring对于Bean的一种第三人称的描述。

有点复杂?没关系,我们举个例子。

假设有一个类:纸盒。它的一个对象是这样描述自己的:我是一个盒子,纸做的,长宽高都是20厘米。听完他的描述,我们基本上能对他有一定认识。那么,不如再听听他朋友的描述:他是一个盒子,纸做的,他的长宽高都是20厘米。只是换了个人称,但是我们还是认识了纸盒君。嗯,没毛病。

这就是Bean和Bean定义。Spring容器中,用Bean定义来描述一个对象,然后在合适的时机,通过反射机制,生成一个对象,交给需要依赖此对象的目标。

有了这个认知后,对于AbstractBeanDefinition中构造方法,就比较好理解了。Bean定义中会包含一系列Bean的相关属性,这些属性,在通过反射生成Bean时,会用到。两个构造方法,分别采用了两种方式来向Bean定义中写入这些属性,一种是直接写入的方式,另一种是拷贝的方式。

理解了构造方法后,再来看其它的一些方法,也是相对容易理解。主要就是对Bean定义中各种属性的set或get。

BeanDefinition的继承体系

接下来,我们将BeanDefinition的继承体系整理一下,如下图:

BeanDefinition的继承体系

AnnotatedBeanDefinition:包含有注解的Bean定义。一般情况下,通过注解的方式得到Bean定义,类型都是该接口的实现类。

AnnotatedGenericBeanDefinition:有@Configuration注解的类,会生成AnnotatedGenericBeanDefinition类型的Bean定义。

ScannedGenericBeanDefinition:有@Component注解的类,会生成ScannedGenericBeanDefinition类型的Bean定义。注意其它继承了@Component的注解,同@Component。

RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition:这个类均继承了AbstractBeanDefinition。从官方文档里,我们得到了以下一些信息:

RootBeanDefinition是最常用的实现类,它对应一般性的<bean>元素标签,GenericBeanDefinition是自2.5以后新加入的bean文件配置属性定义类,是一站式服务类。在配置文件中可以定义父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而没有父<bean>的<bean>就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行抽象。

看完了这些信息,还是觉得不明所以,没关系,我们把这些问题带到后续的学习中。

相关

Spring中,ApplicationContext的继承体系

Spring Boot的优点,有哪些值得我们使用的地方

Spring的Bean,Bean工厂和Bean定义

Spring Boot多环境配置的简单demo

举报/反馈