Spring源码系列二:BeanDefinition对象
BeanDefinition可以看作是一个bean在Spring中的描述。
首先大体介绍BeanDefinition这个对象,它描述了bean的一些基本信息,包括:bean的class名、作用域(单例、原型)、懒加载、FactoryBean、构造函数、属性值、描述以及bean的来源,spring会根据这些信息来实例化bean。
BeanDefinition对象在org.springframework.beans.factory.config包下,我们先看看BeanDefinition的继承规则:
可以看出BeanDefinition接口继承自AttributeAccessor和BeanMetadataElement,所以我们先来看看这两个接口的作用。
AttributeAccessor
这个对象的作用就是用于向任意对象附加元数据或从任意对象访问元数据。
// 用于向任意对象附加元数据或从任意对象访问元数据
public interface AttributeAccessor {
/**
* 将name对应的属性设置为相应的值,这个可以为null,如果为null的话就直接将name对应的属性移除
* 一般来说应该使用完全限定名来防止与其他元数据的属性重叠
* 这里的属性相当于key-value键值对
*/
void setAttribute(String name, @Nullable Object value);
/**
* 获取name对应的属性的值,如果属性不存在则返回null
*/
@Nullable
Object getAttribute(String name);
/**
* 移除name对应的属性,并且返回这个属性的值
*/
@Nullable
Object removeAttribute(String name);
/**
* 判断name对应的属性是否存在,存在则返回true,否则返回false
*/
boolean hasAttribute(String name);
/**
* 返回所有属性的名字
*/
String[] attributeNames();
}
通过查看其源代码,我们可以看出这是spring定义的对bean属性操作的接口,可以对bean的属性进行管理,包括设置和删除属性,判断属性是否存在,返回全部的属性等功能。
BeanMetadataElement
BeanDefinition继承了BeanMetadataElement,说明它可以持有Bean元数据元素,作用是可以持有XML文件的一个bean标签对应的Object。
// 由携带配置源对象的bean元数据元素实现的接口
public interface BeanMetadataElement {
/**
* 返回元数据元素的配置源
*/
@Nullable
default Object getSource() {
return null;
}
}
BeanDefinition对象
BeanDefinition描述一个bean实例,该实例具有属性值、构造函数参数值和由具体实现提供的进一步信息。
这只是一个包含最少功能的接口:主要目的是允许BeanFactoryPostProcessor访问和修改属性值以及bean的其他元数据
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// 单例作用域的标识符,真实值为:"singleton",扩展的bean工厂可能支持更多的作用域
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
// 原型作用域的标识符,真实值为:"prototype",扩展的bean工厂可能支持更多的作用域
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
// 定义了bean的角色,指示BeanDefinition是应用程序的主要部分,通常对应用户自定义的bean
int ROLE_APPLICATION = 0;
// 指示BeanDefinition是某个较大配置的支持部分
int ROLE_SUPPORT = 1;
// 指示BeanDefinition完全作为基础模块,与最终用户无关
int ROLE_INFRASTRUCTURE = 2;
/*
如果BeanDefinition有父BeanDefinition,就设置其父类的名称,可以为空
*/
void setParentName(@Nullable String parentName);
/*
获取BeanDefinition的父BeanDefinition的名称
*/
@Nullable
String getParentName();
/*
设置BeanDefinition对应的class的名称
可以在bean工厂后置处理期间修改类名,通常用解析的类名变体替换原始类名
*/
void setBeanClassName(@Nullable String beanClassName);
/*
获取BeanDefinition对应的当前bean的名称
注意,如果子定义重写/继承其父级的类名,则不必是运行时使用的实际类名。而且,这可能只是调用工厂方法的类,
或者在调用方法的工厂bean引用的情况下,它甚至可能是空的。因此,不要将其视为运行时的最终bean类型,而应仅在
单个bean定义级别将其用于解析目的
*/
@Nullable
String getBeanClassName();
/*
使用指定的新作用域覆盖bean原有的作用域
*/
void setScope(@Nullable String scope);
/*
获取bean的作用域
*/
@Nullable
String getScope();
/*
设置bean是否懒加载
如果false的话,bean将在启动时由执行单例的急切初始化的bean工厂实例化
*/
void setLazyInit(boolean lazyInit);
/*
判断bean是否延迟初始化,只适用于单例bean
*/
boolean isLazyInit();
/*
设置bean初始化时依赖的那些bean
dependsOn一般用于两个bean之间没有显示依赖,但后一个Bean需要用到前一个Bean执行初始方法后的结果。例如在< bean id=“a” dependsOn=“b”/> 时,在初始化a时首先先初始化b,在销毁b之前会先销毁a。
*/
void setDependsOn(@Nullable String... dependsOn);
/*
获取bean依赖的那些bean的名称
*/
@Nullable
String[] getDependsOn();
/*
设置该对象是否可以被其他对象自动装配
设置该bean是否可以被其他需要自动注入的bean获取到
只影响基于type的自动注入,不影响基于name的自动注入
*/
void setAutowireCandidate(boolean autowireCandidate);
/*
返回该bean是否为其他bean自动装配所需要的
*/
boolean isAutowireCandidate();
/*
设置bean是否为被优先自动装配的
如果这个值对于bean自动装配时匹配的多个候选项中的某一个bean为true,那么直接装配值为true的bean
如果其他对象按照类型自动装配时发现有多个符合类型的多个实现bean,如果bean的primary属性为true,则以primary为true的优先,当然如果有多个primary为true,则抛出异常。
*/
void setPrimary(boolean primary);
/*
判断是否被优先自动装配的类
*/
boolean isPrimary();
/*
设置bean要使用的factory bean的名称,而该bean会调用指定的工厂方法
设置bean工厂的方法名,Spring在实例化Bean对象时支持工厂方法设计模式,在初始化bean时不是通过bean的class反射创建 bean实例,而是根据factoryBeanName反射出工厂的实例,然后调用它的实例方法factoryMethodName来创建bean实例。
*/
void setFactoryBeanName(@Nullable String factoryBeanName);
/*
返回设置的工厂方法名称
*/
@Nullable
String getFactoryBeanName();
/*
设置工厂方法,将使用构造函数调用该方法,如果没有指定参数就不使用任何参数。这个方法将会在指定的工厂bean或者本地bean的静态方法中调用
*/
void setFactoryMethodName(@Nullable String factoryMethodName);
/*
返回工厂方法
*/
@Nullable
String getFactoryMethodName();
/*
返回bean的构造函数的参数,返回的实例可以在bean工厂的后置处理器中进行修改
*/
ConstructorArgumentValues getConstructorArgumentValues();
/*
如果有为该bean定义的构造函数参数值则返回true
*/
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
/*
返回要应用于bean的新实例的属性值
*/
MutablePropertyValues getPropertyValues();
/*
如果有为bean定义的属性值则返回true
*/
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}
/*
设置初始化方法的名称
*/
void setInitMethodName(@Nullable String initMethodName);
/*
获得初始化方法的名称
*/
@Nullable
String getInitMethodName();
/*
设置销毁方法的名称
*/
void setDestroyMethodName(@Nullable String destroyMethodName);
/*
获取销毁方法的名称
*/
@Nullable
String getDestroyMethodName();
/*
设置BeanDefinition的角色,为框架提供了指示BeanDefinition角色和重要性的工具
*/
void setRole(int role);
/*
获取BeanDefinition的角色
*/
int getRole();
/*
设置可读的bean定义的描述
*/
void setDescription(@Nullable String description);
/*
获取bean定义的可读的描述
*/
@Nullable
String getDescription();
/*
基于bean类或其他特定元数据,返回此bean定义的可解析类型
*/
ResolvableType getResolvableType();
/*
判断bean是否为Singleton,单独的且可共享的实例将会在此次调用中返回true
*/
boolean isSingleton();
/*
判断bean是否为Prototype,原型实例将会在每次调用中返回true
*/
boolean isPrototype();
/*
判断类是否为抽象的,意味着这不是对特定的实例进行判断,而是判断这个类
*/
boolean isAbstract();
/*
返回此bean定义所来自资源的描述
*/
@Nullable
String getResourceDescription();
/*
返回原始的BeanDefinition
*/
@Nullable
BeanDefinition getOriginatingBeanDefinition();
}
通过上述源码的分析,我们可以看到这个BeanDefinition的大概作用如下:
- 设置BeanDefinition的父BeanDefinition,或者获取其父BeanDefinition的名称
- 设置BeanDefinition所对应的class的全限定类名,或者获取BeanDefinition包装的class的名称
- 设置bean的作用域、是否懒加载、依赖的其他bean
- 设置bean在自动装配中的可见性以及优先级
- 设置BeanDefinition的工厂bean和工厂方法
- 获取bean的构造函数的参数和bean对象的属性值
- 设置bean初始化方法和销毁时的方法
- 设置bean的描述,获取从Bean定义中解析出来的类型
- 判断bean是否为单例、原型、懒加载
- 获取这个BeanDefinition的来源(例如从xml或者注解配置中),获取BeanDefinition应用链的原始BeanDefinition
其实从BeanDefinition可以看出这个类描述了bean的一些基本的定义,spring在这个bean定义的基础上再生产出我们真正要使用的bean,也就是说Spring是根据BeanDefinition中的信息来实例化bean的。
BeanDefinition提供了一系列操作bean元数据的get、set方法,BeanDefinition的操作定义了一套模板,具体的实现交给子类。