1. BeanDefinition的属性
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来自的资源 |
2. 三个子类及属性
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回调函数名,以便进行生命周期回调 |
3. 三个子类的应用及区别
在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
能够在运行时读取和处理这些注解,提供更丰富的功能。
4. BeanDefinition的合并
Spring中提供了多样的BeanDefinition,其最后都会被转换或合并为RootBeanDefinition,就是把子 BeanDefinition
的配置信息和父 BeanDefinition
的配置信息合并起来,形成一个完整的配置信息。合并后的 BeanDefinition
对象包含了 Bean
创建所需要的所有信息,Spring
将使用这个完整的 BeanDefinition
来创建 Bean
实例。
5. BeanDefinition的合并解析
代码位于: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.