BeanDefinition作为接口定义了属性的get、set方法。这些属性基本定义在其直接实现类AbstractBeanDefinition中,各属性的含义如下表所示:
类型 |
名称 |
含义 |
常量 |
SCOPE_DEFAULT |
默认作用域:单例模式 |
AUTOWIRE_NO |
没有自动装配 |
|
AUTOWIRE_BY_NAME |
按名称自动装配 |
|
AUTOWIRE_BY_TYPE |
按类型自动装配 |
|
AUTOWIRE_CONSTRUCTOR |
按最匹配的构造方法自动装配 |
|
AUTOWIRE_AUTODETECT |
对bean类进行内省来确定合适的自动装配策略 |
|
DEPENDENCY_CHECK_NONE |
不进行依赖关系依赖关系检查 |
|
DEPENDENCY_CHECK_OBJECTS |
对对象引用进行依赖关系检查 |
|
DEPENDENCY_CHECK_SIMPLE |
对简单属性进行依赖关系检查 |
|
DEPENDENCY_CHECK_ALL |
对所有属性进行依赖关系检查 |
|
INFER_METHOD |
容器应尝试推断销毁方法名称,而不是显示指定方法名称 |
|
属性变量 |
beanClass |
Bean 的Class对象 |
scope |
作用域,默认为单例 |
|
abstractFlag |
是否是抽象类标记,默认值为false,若为true,则不会实例化该bean |
|
lazyInit |
是否懒加载 |
|
autowireMode |
自动装配模式,默认无 |
|
dependencyCheck |
依赖关系检查,默认无 |
|
dependsOn |
Bean依赖的其他Bean的名称 |
|
autowireCandidate |
这个bean是否是自动装配到其他bean的候选项,默认为true |
|
priary |
这个bean是否是首要的自动装配候选项,默认为false |
|
qulifiers |
自动装配候选项限定符map,key:class对象名称(全类名) |
|
instanceSupplier |
为创建bean实例指定一个回调函数,作为声明性工厂方法的替代方案 |
|
nonPublicAccessAllowed |
是否允许访问非公共的构造函数和方法,默认为true,标识允许 |
|
lenientConstructorResolution |
是否以宽松模式或严格模式解析构造函数,默认为true,为宽松模式 |
|
factoryBeanName |
工厂bean名称 |
|
factoryMethodName |
工厂方法名称 |
|
constructorArgumentValues |
构造函数参数值 |
|
propertyValues |
属性值 |
|
methodOverrides |
当前bean被重写的方法 |
|
initMethodName |
初始化的方法的名称 |
|
destroyMethodName |
销毁的方法的名称 |
|
enforceInitMethod |
指定配置的方法是否为初始化方法,默认为true |
|
enforceDestroyMethod |
指定配置的方法是否为销毁方法,默认为true |
|
synthetic |
beanDefiniton是否是合成的,默认为false |
|
role |
角色提示,指BeanDefinition是应用程序的主要部分。通常是由用户定义的bean |
|
description |
beanDefiniton可读性高的描述 |
|
resource |
beanDefinition来自的资源 |
AbstractBeanDefinition有三个重要的直接子类,他们除了拥有父类的这些属性外,自己也有专门的属性,首先其类图如下所示:
三个直接子类各自的属性如下表所示:
子类 |
属性名称 |
属性含义 |
GenericBeanDefinition |
parentName |
父bean名称 |
ChildBeanDefinition |
parentName |
父bean名称 |
RootBeanDefinition |
decoratedDefinition |
记录了beanName,别名等 |
qualifiedElement |
记录了注解元素 |
|
stale |
beanDefinition是否需要被重新合并 |
|
allowCaching |
是否允许缓存,默认为true |
|
isFactoryMethodUnique |
工厂方法是否唯一,默认为false |
|
resolvedTargetType |
缓存class,表明RootBeanDefinition存储哪个类的信息 |
|
isFactoryBean |
表名该Bean是否是工厂bean |
|
factoryMethodReturnType |
缓存工厂方法的返回类型 |
|
resolvedDestroyMethodName |
缓存已解析的销毁方法名称 |
|
resolvedConstructorOrFactoryMethod |
缓存已解析的构造函数或工厂方法 |
|
constructorArgumentsResolved |
表明构造函数参数是否解析完毕,默认为false |
|
resolvedConstructorArguments |
缓存完成解析的构造函数参数 |
|
preparedConstructorArguments |
缓存待解析的构造函数参数 |
|
postProcessed |
表名是否被MergedBeanDefinitionPostProcessor处理过,默认为false |
|
beforeInstantiationResolved |
在生成代理时使用,表名是否已经生成代理 |
|
externallyManagedConfigMembers |
记录了Contructor、Field、method类型的成员 |
|
externallyManagedInitMethods |
InitializingBean中的init回调函数名,以便进行生命周期回调 |
|
externallyManagedDestroyMethods |
DisposableBean的destroy回调函数名,以便进行生命周期回调 |
在XML文件中定义一个bean时,Spring会创建一个RootBeanDefinition实例,这个实例会保存所有的配置信息,如类名、属性值等;
当一个bean继承了另一个bean时,Spring会为子bean创建一个ChildBeanDefinition,为父bean创建一个RootBeanDefinition;
在配置类中使用@Bean注解定义bean时,Spring会创建一个GenericBeanDefinition实例;
在类上使用注解(如@Component、@Service、@Repository等)来定义一个bean时,Spring会创建一个实现了AnnotatedBeanDefinition接口的实例:AnnotatedGenericBeanDefinition或ScannedGenericBeanDefinition。这个实例会保存类名、类的类型、以及类上的所有注解信息;
GenericBeanDefinition
和AnnotatedBeanDefinition
的主要区别如下:
AnnotatedBeanDefinition
保存了类上的注解信息,而GenericBeanDefinition
没有。这就使得Spring
能够在运行时读取和处理这些注解,提供更丰富的功能。
Spring中提供了多样的BeanDefinition,其最后都会被转换或合并为RootBeanDefinition,就是把子 BeanDefinition
的配置信息和父 BeanDefinition
的配置信息合并起来,形成一个完整的配置信息。合并后的 BeanDefinition
对象包含了 Bean
创建所需要的所有信息,Spring
将使用这个完整的 BeanDefinition
来创建 Bean
实例。
代码位于:AbstractBeanFactory#getMergedBeanDefinition
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
// 父bean为空
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
// 原始的BeanDefinition为RootBeanDefinition,直接克隆
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
// 原始的BeanDefinition不是RootBeanDefinition,则new一个
mbd = new RootBeanDefinition(bd);
}
}
else {
// 父bean不为空,需要合并
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
// 获取map中parentBeanName对应的RootBeanDefinition
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without a ConfigurableBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// 深拷贝
mbd = new RootBeanDefinition(pbd);
// 子bean初始化BeanDefinition的相关信息覆盖掉继承自RootBeanDefinition的相同信息
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
逻辑流程图如下所示:
总结如下:
若bean没有父亲,将当前beanDefinition通过克隆或深拷贝方式生成一个新的RootBeanDefinition,并返回;
若bean有父亲,将父beanDefinition通过克隆或深拷贝方式生成一个新的RootBeanDefinition,再将子beanDefiniton属性覆盖RootBeanDefiniton的相同信息,并返回该RootBeanDefinition.