BeanDefinition是在Spring 容器创建过程中用来描述Bean的一个对象,包含了Bean属性值、构造函数值以及一些其他定义的信息,
在容器创建之后,按照加载的BeanDefinition对象去创建相应的Bean。
从基础的 BeanDefinition 接口中提供的方法来看,一个BeanDefinition 有以下行为,大部分方法都是为了构建Bean的描述的,由此也能看出一个Bean应该具有哪些特征:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 设置父级BeanDefinition的名字,由此可知一个Bean定义对象支持关联一个父级的定义对象
void setParentName(@Nullable String parentName);
// 设置要定义Bean的类名
void setBeanClassName(@Nullable String beanClassName);
// 设置要定义Bean的作用域,即我们熟知的singleton、prototype等等
void setScope(@Nullable String scope);
// 设置要定义Bean是否延迟初始化(懒加载)
void setLazyInit(boolean lazyInit);
// 设置该Bean要依赖的其他Bean名称,这些Bean将优先初始化
void setDependsOn(@Nullable String... dependsOn);
// 设置该Bean是否自动装配到其他Bean中,仅影响按类型装配
void setAutowireCandidate(boolean autowireCandidate);
// 设置Bean初始化方法
void setInitMethodName(@Nullable String initMethodName);
// 设置Bean销毁方法
void setDestroyMethodName(@Nullable String destroyMethodName);
}
以上方法均有一个对应的getter方法,用于获取配置的值。此外还包括Bean的属性值、构造函数参数值等定义信息。
此外该接口还继承了另外两个接口:
Spring 中提供了一系列实现类来支持Bean定义对象的使用,通过不同的实现能够解析不同的Bean配置元数据,达到不同方式创建Bean的目的,例如传统xml配置文件形式、和注解形式。同时这些实现还支持在后置处理器中修改Bean的定义信息,提供更多扩展性能力。
上图为整个BeanDefinition体系的继承和实现关系图,简单介绍一下上层接口的作用,再详细学习一下几个具体实现类的逻辑
AbstractBeanDefinition:对BeanDefinition接口提供能力的一些基本公共实现和创建对象的基础处理,维护一些必须的成员变量。
AttributeAccessorSupport:是对AttributeAccessor接口的支持,维护了存储属性集合的成员变量,实现了具体的设置和访问能力(使用Map存储具体元数据属性)。
BeanMetadataAttributeAccessor:实现了BeanMetadataElement设置元数据数据源对象的能力,维护元数据的数据源对象;也对AttributeAccessorSupport进行了扩展,增加了专门用来设置元数据属性的方法,语义化更强,更符合单一职责。
public void addMetadataAttribute(BeanMetadataAttribute attribute) {
super.setAttribute(attribute.getName(), attribute);
}
AnnotatedBeanDefinition:是对BeanDefinition接口的扩展,提供了获取注解形式定义的Bean配置元数据的方法。
GenericBeanDefinition 标准的Bean定义对象
该类是注册Bean最常用的一个定义类,主要功能继承自AbstractBeanDefinition,并扩展对父定义的支持,兼容了RootBeanDefinition
和ChildBeanDefinition
。先来看一下AbstractBeanDefinition中的成员变量,主要用来存储一个Bean定义所需的一些配置元数据:
// 存储Bean所属的类型,持有该Bean类对象的引用
private volatile Object beanClass;
// 存储Bean的作用域
private String scope = SCOPE_DEFAULT;
// 标识该Bean是否延迟加载
private Boolean lazyInit;
// 表示Bean的自动装配模式
private int autowireMode = AUTOWIRE_NO;
// 存储Bean依赖的其他Bean的名字
private String[] dependsOn;
// 存储Bean配置的构造函数参数值信息
private ConstructorArgumentValues constructorArgumentValues;
// 存储Bean配置的属性值信息
private MutablePropertyValues propertyValues;
// 存储Bean自定义初始化方法名称,将在Bean初始化的时候调用
private String initMethodName;
// 存储Bean自定义销毁方法名称,将在Bean销毁之前调用
private String destroyMethodName;
// 读取Bean定义配置的来源
private Resource resource;
GenericBeanDefinition单独维护一个成员变量支持子级对象的创建:
// 存储父级定义对象的名称
private String parentName;
GenericBeanDefinition包含两个构造器:
overrideFrom(BeanDefinition other)
,都是将参数对象的上述字段值设置到新对象里面。下面列举一些主要方法,其他方法均是对成员变量的赋值和查询操作,感兴趣可查看源码:
// 用于设置Bean定义对象的默认值,接收一个默认值对象BeanDefinitionDefaults
void applyDefaults(BeanDefinitionDefaults defaults);
// 解析相关Bean的类,如果类没有加载,会先加载该类
Class<?> resolveBeanClass(@Nullable ClassLoader classLoader);
// 返回相关Bean的解析类型
ResolvableType getResolvableType();
// 返回Bean的属性注入方式,如果有无参构造,就用setter方法注入,否则是构造器注入
int getResolvedAutowireMode();
RootBeanDefinition父级Bean定义对象
该对象既可以当做一个普通的Bean定义对象,也可以当做子Bean定义对象的父级,子对象将继承父对象中的配置项。这里赋予了Bean定义的继承能力和合并能力,最大化的补全了Bean定义的属性。
随着越来越多注解声明Bean的使用,推荐使用GenericBeanDefinition处理通用的Bean定义对象。
ChildBeanDefinition子级Bean定义对象
该对象是作为上面父级对象的子级存在的,不能单独存在,用来表示具备继承配置的Bean定义存在,推荐使用GenericBeanDefinition。
注解方式声明Bean
AnnotatedBeanDefinition接口提供了获取声明Bean的注解的元数据的能力:
// 获取Bean定义的注解元数据
AnnotationMetadata getMetadata();
// 获取Bean定义的工厂方法的元数据
MethodMetadata getFactoryMethodMetadata();
AnnotatedGenericBeanDefinition是AnnotatedBeanDefinition接口的主要实现类,并且继承了GenericBeanDefinition的所有能力。维护了存储注解元数据metadata
和工厂方法原数据的变量factoryMethodMetadata
,并实现了接口的方法。主要的两个构造器如下:
//接收Bean的类对象参数
public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
// 设置Bean的类型,在上文AbstractBeanDefinition中定义
setBeanClass(beanClass);
// 设置该给的注解原数据,通过Class对象反射获得类上的注解信息
this.metadata = AnnotationMetadata.introspect(beanClass);
}
// 接收注解元数据参数
public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
Assert.notNull(metadata, "AnnotationMetadata must not be null");
// 通过注解元数据对象解析出对应Bean的类型
if (metadata instanceof StandardAnnotationMetadata) {
setBeanClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass());
}
else {
setBeanClassName(metadata.getClassName());
}
// 设置元数据对象
this.metadata = metadata;
}
ScannedGenericBeanDefinition 主要用于用于创建包扫描出的Bean定义对象,支持通过类的元数据进行创建对象。后续将在使用中再次介绍这个类型。
// 存储该定义对象的注解
private final AnnotationMetadata metadata;
public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
Assert.notNull(metadataReader, "MetadataReader must not be null");
// 获取参数中提供的注解元数据对象
this.metadata = metadataReader.getAnnotationMetadata();
// 获取参数中提供的类名称
setBeanClassName(this.metadata.getClassName());
}
// 该接口类型支持对类文件元数据的访问
public interface MetadataReader {
// 对源文件资源的访问
Resource getResource();
// 对类文件类的元数据访问
ClassMetadata getClassMetadata();
// 对类文件的类的注解元数据访问
AnnotationMetadata getAnnotationMetadata();
}
ConfigurationClassBeanDefinition是ConfigurationClassBeanDefinitionReader
中的一个内部类,ConfigurationClassBeanDefinitionReader
是加载由用户自定义的@Configuration
标注的类中Bean,因此ConfigurationClassBeanDefinition就是为此类Bean创建定义对象的。不再展示该类代码,在后面解析Spring注册BeanDefinition代码中会介绍如何使用。
BeanDefinition是一个对Spring中的Bean的定义对象,描述了创建一个标准Bean所需的众多属性。Spring内置了六种实现类来支持多中Bean定义形式:xml格式配置、注解配置、包自动扫描和@Configuration
四种形式。加载并注册BeanDefinition是Spring工厂创建的一个重要步骤,后续的Bean创建会依赖BeanDefinition的定义去严格创建。
本文只了解一下BeanDefinition的定义和大家族中各个类的使用形式以及主要实现逻辑,下一篇文章将介绍Sping是如何为Bean注册这些定义对象的。
原文地址