SpringBoot启动分析-BeanDefinition

BeanDefinition

BeanDefinition 是一个描述 Bean 信息的接口,它描述和定义了一个创建 bean 的所有基本信息,其中就包括了以下属性

  1. parentName: 双亲 bean 的名称
  2. beanClassName: bean 的类名,但一定有,因为如果该 bean 是由工厂bean 产生的,那么这里的 beanClassName 为空
  3. scope: 作用域,如 singleton, prototype
  4. lazyInit: 是否为懒加载,如果被设置为 lazy = true,那么这个 bean 会在使用的时候才会被实例化
  5. factoryBeanName:生产这个 bean 的工厂名
  6. propertyValues: 属性值
  7. role: bean 的角色类型,包括了 APPLICATION, SUPPORT, INFRASTRUCTURE




AbstractDefinition

AbstractDefinition 实现了 BeanDefinition 接口,为子类 RootBeanDefiniton, ChildBeanDefinition, GenericBeanDefinition 提供了 BeanDefinition 公用逻辑的封装,主要封装有以下:

  1. 定义了公共的构造函数
  2. 为属性值定义了 getter/ setter 等方法,方便获取设置属性值
  3. 提供了 overrideFrom() 用于覆盖 当前bean 的定义 及 applyDefaults() 用于设置 bean 的默认属性值



值得一提的是,AbstractBeanDefinition 同时实现了 BeanMetadataAttributeAccessor,即为 BeanDefinition 扩展了以下功能 source, attreibute 等功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// AttributeAccessorSupport 可以为 bean 修改对应的 attrbute
// BeanMetadataElement 可以为 bean 设置对应的 source
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement {

// 设置 configuration source
public void setSource(@Nullable Object source) {
this.source = source;
}

@Override
@Nullable
public Object getSource() {
return this.source;
}

@Nullable
public BeanMetadataAttribute getMetadataAttribute(String name) {
return (BeanMetadataAttribute) super.getAttribute(name);
}

@Override
public void setAttribute(String name, @Nullable Object value) {
super.setAttribute(name, new BeanMetadataAttribute(name, value));
}

@Override
@Nullable
public Object getAttribute(String name) {
BeanMetadataAttribute attribute = (BeanMetadataAttribute) super.getAttribute(name);
return (attribute != null ? attribute.getValue() : null);
}

@Override
@Nullable
public Object removeAttribute(String name) {
BeanMetadataAttribute attribute = (BeanMetadataAttribute) super.removeAttribute(name);
return (attribute != null ? attribute.getValue() : null);
}


RootBeanDefinition & ChildBeanDefinition

RootBeanDefinition 不能设置 parent bean,而 ChildBeanDefinition 必须设置 parent bean,设置的方式通常由构造函数实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class ChildBeanDefinition extends AbstractBeanDefinition {

@Nullable
private String parentName;

public ChildBeanDefinition(String parentName) {
super();
this.parentName = parentName;
}

public ChildBeanDefinition(String parentName, MutablePropertyValues pvs) {
super(null, pvs);
this.parentName = parentName;
}

public ChildBeanDefinition(
String parentName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) {

super(cargs, pvs);
this.parentName = parentName;
}


RootBeanDefinition 在 Spring 容器的创建过程中或者是运行期间被频繁使用,是因为它代表了一种特定的 merged bean definition,即能够表示出它由多个原始的 bean 彼此继承之间的关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// AbstractBeanFactory.class
// 合并的过程是,通过递归不断合并 parent & child,通过构造函数中的属性重新赋值,得到新的 BeanDefinition,最终返回 RootBeanDefinition
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {

// 获取 map mergedBeanDefinitions 的对象锁
synchronized (this.mergedBeanDefinitions) {

// 定义一个 RootBeanDefinition 引用
RootBeanDefinition mbd = 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) {

// parentName == null,说明当前已经是 RootBeanDefinition,那么就直接使用,clone(this)并重新赋值
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
// 如果存在 parentName, 那么说明当前 BeanDefinition 为 ChildBeanDefinition
// 那么就继续调用 getMergedBeanDefinition(),递归获取 RootBeanDefinition,并不断的合并创建对象并属性拷贝
BeanDefinition pbd;
try {

// 这里的 transFormedBeanName 是为了获取 bean 的真正名称
// 因为如果是 factoryBean 创建出来的对象,那么它的名称中将带有 &,而目的就是为了 remove it
String parentBeanName = transformedBeanName(bd.getParentName());
if (!beanName.equals(parentBeanName)) {
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 an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
// 重新实例化一个 RootBeanDefinition 并进行属性赋值
mbd = new RootBeanDefinition(pbd);
// 覆盖旧属性
mbd.overrideFrom(bd);
}

// Set default singleton scope, if not configured before.
// 如果之前没有配置作用域,那么就设置默认的 singleton scope
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.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);
}
}

return mbd;
}
}


Merged & Save

可以看到,每次 RootBeanDefinition merge ChildBeanDefinition 的大致流程如下:

  1. new RootBeanDefinition(child)
  2. merge process
  3. overrideFrom(child)

那么,在合并的过程中,除了一些基本的属性赋值,有哪些属性被合并到 rootBeanDefinition 中呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 在每次合并的时候,都会实例化 new RootBeanDefinition(this)
// 而在 RootBeanDefiniition 的构造函数中,会调用 super(this),那么就是调用 AbstractBeanDefiniiton constructor
// AbstractBeanDefinition.class
protected AbstractBeanDefinition(BeanDefinition original) {

// 这里会调用 AttributeAccessorSupport.copyAttributesForm()
copyAttributesFrom(original);
}


// AttributeAccessorSupport.class
// 这里会将 BeanDefinition 中的 attributes 进行遍历加入到当前 parentBeanDefinition 的 attribute 中
protected void copyAttributesFrom(AttributeAccessor source) {
Assert.notNull(source, "Source must not be null");
String[] attributeNames = source.attributeNames();
for (String attributeName : attributeNames) {
setAttribute(attributeName, source.getAttribute(attributeName));
}
}

// AbstractBeanDefinition.class
// 同理, 在 overrideFrom(),会将 child 的 constructorArgValue,propertyValue,methodOverrides 中的属性保留到当前 bd的属性中
public void overrideFrom(BeanDefinition other) {
if (other instanceof AbstractBeanDefinition) {
AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
}

if (otherAbd.hasConstructorArgumentValues()) {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
}
if (otherAbd.hasPropertyValues()) {
getPropertyValues().addPropertyValues(other.getPropertyValues());
}
if (otherAbd.hasMethodOverrides()) {
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
}
}


总结

在构建 bean 的过程中,会频繁使用到 BeanDefinition , BeanDefinition 作为通用接口,它规定了 Bean 的一些基本定义,为了更好的使用 BeanDefinition,AbstractBeanDefinition 对其进行了封装,加入了构造过程及 getter/setter 便于子类的使用调用,具体的实现分别为 RootBeanDefinition 和 ChildBeanDefinition ,它们用来表示 BeanDefinition 之间的一种继承关系,当我们在实例化 Bean 的时候,通常只需使用到 RootBeanDefinition ,但由于多个 BeanDefinition 之间的属性依赖关系,所以就需要对这些 AbstractBeanDefinition 进行合并,这个过程就就会进行属性的赋值和属性的记录。

引用