Spring 源码分析(二)——GenericBeanDefinition 分析
BeanDefinition
中存储着 Bean
的定义信息,它具有属性值、构造函数参数值以及具体实现 Bean
提供的进一步信息,在学习 Spring
的 Bean
初始化流程之前,还是非常有必要先了解一下 BeanDefinition
。
一、注册 Bean 示例
首先,本文先举一个使用 BeanDefinition
创建 Bean
的小例子:
import com.nineya.spring.entity.Post;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import java.util.ArrayList;
import java.util.List;
public class SpringMain {
public static void main(String[] args) {
// 创建bean工厂
DefaultListableBeanFactory context = new DefaultListableBeanFactory();
//构造bean定义
GenericBeanDefinition gbd = new GenericBeanDefinition();
gbd.setBeanClass(Post.class);
// 设置属性
List<PropertyValue> propertyValues = new ArrayList<>();
propertyValues.add(new PropertyValue("id", 123L));
propertyValues.add(new PropertyValue("title", "title"));
gbd.setPropertyValues(new MutablePropertyValues(propertyValues));
//注册到环境上下文
context.registerBeanDefinition("post", gbd);
// 通过class取得bean
Post post = context.getBean(Post.class);
System.out.println(post + " : " + post.hashCode());
// 通过名称取得bean
post = (Post) context.getBean("post");
System.out.println(post + " : " + post.hashCode());
}
}
执行结果输出:
Post(id=123, title=title, categories=null, tags=null, content=null) : 1339167804
Post(id=123, title=title, categories=null, tags=null, content=null) : 1339167804
二、GenericBeanDefinition 结构
GenericBeanDefinition
类继承关系图如下:
逐个对 GenericBeanDefinition
继承的类/接口进行分析:
BeanMetadataElement 接口: BeanMetadataElement
提供了获取数据源的方式,也就是可以指导 Bean
是来自哪个类,由携带配置源对象的 Bean
元数据元素实现的接口。
接口 | 说明 |
---|---|
Object getSource() | 返回此元数据元素的配置源 |
AttributeAccessorSupport 抽象类: 支持 AttributeAccessor
属性存取接口,内部使用的 LinkedHashMap
,提供
所有方法的基本实现,由子类扩展。
接口 | 说明 |
---|---|
void setAttribute(String name, @Nullable Object value) | 设置属性 |
Object getAttribute(String name) | 取得属性 |
Object removeAttribute(String name) | 删除并返回属性 |
boolean hasAttribute(String name) | 判断属性是否存在 |
String[] attributeNames() | 取得所有属性的名称 |
以上这两个接口的实现皆与
GenericBeanDefinition
无关联,这是公共的基础类。
BeanMetadataAttributeAccessor 类: 将元数据参数封装为 BeanMetadataAttribute
,用于 Bean
的元数据和属性上下文操作的实现类。
接口 | 说明 |
---|---|
void setSource(@Nullable Object source) | 为这个元数据元素设置配置源 |
void addMetadataAttribute(BeanMetadataAttribute attribute) | 将给定的BeanMetadataAttribute添加到该访问器的属性集 |
BeanMetadataAttribute getMetadataAttribute(String name) | 在这个访问器的属性集中查找给定的BeanMetadataAttribute |
BeanDefinition 接口
接口 | 说明 |
---|---|
void setParentName(@Nullable String parentName) | 设置此 bean 定义的父定义的名称(如果有的话) |
String getParentName() | 返回此 bean 定义的父定义的名称(如果有的话) |
void setBeanClassName(@Nullable String beanClassName) | 指定此 bean 定义的 bean 类名。类名可以在 bean 工厂后期处理期间修改,通常是用解析后的类名替换原来的类名 |
String getBeanClassName() | 返回此 bean 定义的当前bean类名称。注意,这并不一定是运行时使用的实际类名,例如子定义覆盖/继承其父类名。 |
void setScope(@Nullable String scope) | 重写此 bean 的目标范围,指定一个新的范围名 |
String getScope() | 返回此 bean 的当前目标作用域的名称 |
void setLazyInit(boolean lazyInit) | 设置该 bean 是否应该延迟初始化 |
boolean isLazyInit() | 返回该 bean 是否应该延迟初始化,即在启动时实例化 |
void setDependsOn(@Nullable String… dependsOn) | 设置此 bean 所依赖的初始化 bean 的名称, bean 工厂将保证这些 bean 首先被初始化 |
String[] getDependsOn() | 返回此 bean 所依赖的初始化 bean 的名称 |
void setAutowireCandidate(boolean autowireCandidate) | 设置该 bean 是否为自动连接到其他 bean 的候选 bean |
boolean isAutowireCandidate() | 返回该 bean 是否是自动连接到其他 bean 的候选 bean |
void setPrimary(boolean primary) | 设置此 bean 是否为主要自动装配候选 |
boolean isPrimary() | 返回此 bean 是否是自动装配的主要候选 |
void setFactoryBeanName(@Nullable String factoryBeanName) | 指定要使用的工厂 bean 名称 |
String getFactoryBeanName() | 返回工厂 bean 名称(如果有的话) |
void setFactoryMethodName(@Nullable String factoryMethodName) | 指定一个工厂方法,该方法将使用构造函数参数调用,如果没有指定参数,则不使用参数调用。该方法将在指定的工厂 bean 上调用,或者作为本地 bean 类上的静态方法调用。 |
String getFactoryMethodName() | 返回一个工厂方法 |
ConstructorArgumentValues getConstructorArgumentValues() | 返回此 bean 的构造函数参数值 |
boolean hasConstructorArgumentValues() | 判断此 bean 是否定义了构造函数参数值 |
MutablePropertyValues getPropertyValues() | 返回应用于 bean 的新实例的属性值 |
boolean hasPropertyValues() | 判断此 bean 是否定义了属性值 |
void setInitMethodName(@Nullable String initMethodName) | 设置初始化器方法的名称 |
String getInitMethodName() | 返回初始化方法的名称 |
void setDestroyMethodName(@Nullable String destroyMethodName) | 设置销毁方法的名称 |
String getDestroyMethodName() | 返回销毁方法的名称 |
void setRole(int role) | 为这个 BeanDefinition 设置角色提示 |
int getRole() | 获取这个 BeanDefinition 的角色提示 |
void setDescription(@Nullable String description) | 设置此 bean 定义的人类可读的描述 |
String getDescription() | 取得此 bean 定义的人类可读的描述 |
ResolvableType getResolvableType() | 根据 bean 类或其他特定元数据,返回此 bean 定义的可解析类型 |
boolean isSingleton() | 判断此 bean 是否是单例 |
boolean isPrototype() | 判断此 bean 是否是原型 |
boolean isAbstract() | 返回此 bean 是否是“抽象的”,即不需要实例化 |
String getResourceDescription() | 返回此 bean 定义所来自的资源的描述(以便在出现错误时显示上下文) |
BeanDefinition getOriginatingBeanDefinition() | 返回原始的 BeanDefinition |
AbstractBeanDefinition 抽象类: AbstractBeanDefinition
是具体的、BeanDefinition
类的基类,分解出 GenericBeanDefinition
、RootBeanDefinition
和 ChildBeanDefinition
的公共属性和逻辑。
接口 | 说明 |
---|---|
void overrideFrom(BeanDefinition other) | 使用给定 BeanDefinition 定义重新当前 BeanDefinition 中的设置 |
void applyDefaults(BeanDefinitionDefaults defaults) | 将提供的默认值应用到此 bean |
void setBeanClass(@Nullable Class<?> beanClass) | 为这个 bean 指定类 |
Class<?> getBeanClass() throws IllegalStateException | 返回 bean 定义的指定类 |
boolean hasBeanClass() | 返回该定义是否指定了 bean 类 |
Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) | 确定被包装bean的类,如果需要,从指定的类名解析它 |
void setAbstract(boolean abstractFlag) | 默认为“false”。指定 true 告诉 bean 工厂在任何情况下都不要尝试实例化 bean |
Boolean getLazyInit() | 返回该 bean 是否应该延迟初始化 |
void setAutowireMode(int autowireMode) | 设置自动装配模式。这决定是否会发生 bean 引用的自动检测和设置 |
int getAutowireMode() | 返回 bean 定义中指定的自动装配模式 |
int getResolvedAutowireMode() | 返回已解析的自动装配代码 |
void setDependencyCheck(int dependencyCheck) | 设置依赖项检查代码 |
int getDependencyCheck() | 返回依赖项检查代码 |
addQualifier(AutowireCandidateQualifier qualifier) | 注册一个用于自动装配候选解析的限定符,以限定符的类型名称为键值 |
boolean hasQualifier(String typeName) | 返回此 bean 是否具有指定的限定符 |
AutowireCandidateQualifier getQualifier(String typeName) | 返回映射到所提供类型名称的限定符 |
Set<AutowireCandidateQualifier> getQualifiers() | 返回所有已注册的限定符 |
void copyQualifiersFrom(AbstractBeanDefinition source) | 将所提供的 AbstractBeanDefinition 中的限定符复制到当前 BeanDefinition |
public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) | 指定用于创建 bean 实例的回调,作为声明式指定工厂方法的替代方法 |
Supplier<?> getInstanceSupplier() | 返回用于创建 bean 实例的回调(如果有的话) |
void setNonPublicAccessAllowed(boolean nonPublicAccessAllowed) | 指定是否允许访问非公共构造函数和方法,如果外部化元数据指向它们 |
boolean isNonPublicAccessAllowed() | 返回是否允许访问非公共构造函数和方法 |
void setLenientConstructorResolution(boolean lenientConstructorResolution) | 指定是否在宽限模式下解析构造函数 |
boolean isLenientConstructorResolution() | 返回以宽松模式还是严格模式解析构造函数 |
void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) | 为这个 bean 指定构造函数参数值 |
void setPropertyValues(MutablePropertyValues propertyValues) | 指定此 bean 的属性值(如果有的话) |
void setMethodOverrides(MethodOverrides methodOverrides) | 为 bean 指定方法重写(如果有的话) |
MethodOverrides getMethodOverrides() | 返回 IoC 容器要覆盖的方法的信息。如果没有方法重写,该参数将为空。 |
boolean hasMethodOverrides() | 是否为此 bean 定义了方法重写 |
void setEnforceInitMethod(boolean enforceInitMethod) | 指定配置的初始化方法是否为默认值 |
boolean isEnforceInitMethod() | 指示配置的初始化方法是否为默认值 |
void setEnforceDestroyMethod(boolean enforceDestroyMethod) | 设置配置的销毁方法是否为默认值 |
boolean isEnforceDestroyMethod() | 指定配置的销毁方法是否为默认值 |
void setSynthetic(boolean synthetic) | 设置这个 bean 定义是否是“合成的” |
boolean isSynthetic() | 返回此 bean 定义是否是“合成的”,即不是由应用程序本身定义的 |
void setResource(@Nullable Resource resource) | 设置此 bean 定义所来自的资源(以便在出现错误时显示上下文) |
setResourceDescription(@Nullable String resourceDescription) | 设置此 bean 定义所来自的资源的描述(以便在出现错误时显示上下文) |
void setOriginatingBeanDefinition(BeanDefinition originatingBd) | 如果有的话,设置原始的(例如装饰过的) BeanDefinition |
void validate() throws BeanDefinitionValidationException | 验证这个 BeanDefinition |
void prepareMethodOverrides() throws BeanDefinitionValidationException | 验证并准备为此 bean 定义的方法重写。检查具有指定名称的方法是否存在 |
void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException | 验证并准备给定的方法重写。检查具有指定名称的方法是否存在,如果没有找到则将其标记为未重载 |