Spring源码阅读:BeanDefinition接口

前面说到 BeanDefinitionRegistry 是用来管理 BeanDefinition 的注册中心,但是还没看到 BeanDefinition 长什么样,下面就来了解下。

BeanDefinition 接口的继承结构

BeanDefinition 是一个接口,它用来描述 bean 实例,包括 bean 的属性值(property values)、作用范围(scope)、是否为 autowire 的首选(isPrimary)等。BeanDefinition 继承了两个接口,如下图所示

image-20200117003507554

下面先来了解下这两个接口

AttributeAccessor 接口

AttributeAccessor 定义了用于访问任意对象元数据的规范,它的方法定义如下:

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
public interface AttributeAccessor {
/**
* 设置name定义的属性值,如果属性值为null则将其移除
*/
void setAttribute(String name, @Nullable Object value);

/**
* 获取属性值
*/
Object getAttribute(String name);

/**
* 移除属性
*/
Object removeAttribute(String name);

/**
* 判断属性名是否存在
*/
boolean hasAttribute(String name);

/**
* 获取所有的属性名
*/
String[] attributeNames();
}

AttributeAccessorSupport 是该接口的一个实现,它的核心数据结构是一个 Map,所有的 「name -> 属性值」都保存在这个 Map 中

1
2
3
4
5
/** 
* key: name
* value: attribute
*/
private final Map<String, Object> attributes = new LinkedHashMap<>();
image-20200118002613747

这个类比较简单,主要看下 setAttribute 和 copyAttributesFrom 方法。setAttribute 的代码如下:

  1. 当 value 不为空时,直接添加到 Map 中
  2. 当 value 为空时,则将 name 对应的属性值从 Map 中移除
1
2
3
4
5
6
7
public void setAttribute(String name, @Nullable Object value) {
if (value != null) {
this.attributes.put(name, value);
} else {
removeAttribute(name);
}
}

copyAttributesFrom 方法是留给子类使用的,它的作用是深度拷贝一个 AttributeAccessor

1
2
3
4
5
6
protected void copyAttributesFrom(AttributeAccessor source) {
String[] attributeNames = source.attributeNames();
for (String attributeName : attributeNames) {
setAttribute(attributeName, source.getAttribute(attributeName));
}
}

BeanMetadataElement 接口

BeanMetadataElement 只有一个方法 getSource,用于获取 metadata element 对应的可配置的源对象

1
2
3
public interface BeanMetadataElement {
Object getSource();
}

BeanMetadataAttribute 是 BeanMetadataElement 的一个简单实现。

作为 bean definition 的一部分,它用于持有一个键值对形式的属性,同时还会保存对应的源对象

除了保存 source 对象之外,BeanMetadataAttribute 还包含另外两个属性:name 和 value,用于保存属性名字和值:

1
2
3
4
5
6
// 属性的名字
private final String name;
// 属性的值
private final Object value;
// 源对象
private Object source;
image-20200118002353955

BeanMetadataAttributeAccessor 实现

BeanMetadataAttributeAccessor 同时实现了 AttributeAccessor 和 BeanMetadataElement 两个接口,它的继承结构如下图所示:

image-20200118003452774

可以看到,它继承了 AttributeAccessorSupport 类,可以使用其提供的方法来操作属性值,例如 addMetadataAttribute 方法直接调用 setAttribute 保存 BeanMetadataAttribute

1
2
3
public void addMetadataAttribute(BeanMetadataAttribute attribute) {
super.setAttribute(attribute.getName(), attribute);
}

其他的 MetadataAttribute 操作实现类似。

它同时还实现了 BeanMetadataElement 接口,新增了属性

1
private Object source

同时提供了 get 和 set 方法

1
2
3
4
5
6
7
8
public void setSource(@Nullable Object source) {
this.source = source;
}

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

BeanDefinition 接口的方法

BeanDefinition 用于描述 bean 实例,通常是根据 spring xml 中的 bean 配置生成的 BeanDefinition,当然也可以根据注解或其他源数据生成。BeanDefinition 中的方法可以参考 xml 中的 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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

/**
* scope 为 "singleton"
*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

/**
* scope 为 "prototype"
*/
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


/**
* 表示 BeanDefinition 是应用的主要部分,通常是用户定义的 bean
*/
int ROLE_APPLICATION = 0;

/**
* 表示 BeanDefinition 是一个大的配置的支持部分
*/
int ROLE_SUPPORT = 1;

/**
* 表示 BeanDefinition 是基础框架的一部分,用户无需关心
*/
int ROLE_INFRASTRUCTURE = 2;

/**
* 设置父级 bean definition 的名字
*/
void setParentName(@Nullable String parentName);

/**
* 设置 bean definition 对应的 className,可以在 bean factory 的后处理过程中修改掉
*/
void setBeanClassName(@Nullable String beanClassName);

/**
* 设置 bean 的 scope,例如 SCOPE_SINGLETON 或 SCOPE_PROTOTYPE
*/
void setScope(@Nullable String scope);

/**
* 设置 bean 是否要延迟初始化,如果设置为 false,会在 bean factory 启动时执行初始化
*/
void setLazyInit(boolean lazyInit);

/**
* 设置依赖的 bean 的名字,bean factory 会保证这些 bean 先初始化
*/
void setDependsOn(@Nullable String... dependsOn);

/**
* 设置是否把该 bean 作为 autowire 到其他 bean 的候选。这个对 @Reference 没影响
*/
void setAutowireCandidate(boolean autowireCandidate);

/**
* 设置是否把该 bean 作为 autowire 的首选
*/
void setPrimary(boolean primary);

/**
* 设置 factory bean 的名字
*/
void setFactoryBeanName(@Nullable String factoryBeanName);

/**
* 设置 factory 方法名
*/
void setFactoryMethodName(@Nullable String factoryMethodName);

/**
* 返回构造参数值。返回的实例可以被 bean factory 后处理
*/
ConstructorArgumentValues getConstructorArgumentValues();

/**
* 返回要应用到新的 bean 实例的属性值
*/
MutablePropertyValues getPropertyValues();

/**
* 设置 initializer 方法名
* @since 5.1
*/
void setInitMethodName(@Nullable String initMethodName);

/**
* 设置 destroy 方法名
* @since 5.1
*/
void setDestroyMethodName(@Nullable String destroyMethodName);

/**
* 设置 role
* @see #ROLE_APPLICATION
* @see #ROLE_SUPPORT
* @see #ROLE_INFRASTRUCTURE
*/
void setRole(int role);

/**
* 设置一个 human-readable 的描述,例如在 xml 中通过 description 配置
* @since 5.1
*/
void setDescription(@Nullable String description);

/**
* 是否为 Singleton,对应 SCOPE_SINGLETON
*/
boolean isSingleton();

/**
* 是否为 Prototype,对应 SCOPE_PROTOTYPE
*/
boolean isPrototype();

/**
* 是否为 abstract 的,是的话意味着不能实例化
*/
boolean isAbstract();

/**
* 返回资源的描述
*/
String getResourceDescription();

/**
* 返回原始的 BeanDefinition,没有的话返回 null
* 链式调用该方法,最终可获取到由用户定义的 BeanDefinition
*/
BeanDefinition getOriginatingBeanDefinition();
}

总结一下 BeanDefinition 的主要属性

属性含义
scope作用范围,例如 singleton、prototype 等
lazyInit是否延迟初始化
className对应的类的名字
parentName父级 bean definition 的名字
dependsOn依赖的 bean 的名字
autowireCandidate是否为 autowire 的候选者
primary是否为 autowire 的首选
factoryBeanNamefactoryBean 的名字
factoryMethodName工厂方法的名字
initMethodName初始化方法的名字
destroyMethodName销毁方法的名字
ConstructorArgumentValues构造参数值
MutablePropertyValuesbean 实例的属性值
rolerole 类型:APPLICATION、SUPPORT、INFRASTRUCTURE
0%