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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
/**
* 解析 <bean> 元素中所有的 <property> 子元素
*/
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
// 获取对应 <bean> 元素中所有的 <property> 子元素,逐一解析
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 对 <property> 子元素进行详细解析
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
parsePropertyElement((Element) node, bd);
}
}
}
/**
* 详细解析 <property> 元素
*/
public void parsePropertyElement(Element ele, BeanDefinition bd) {
// 获取 <property> 元素的名字
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
// 如果一个 Bean 中已经有同名的 property 存在,则不进行解析,直接返回。
// 即如果在同一个 Bean 中配置同名的 property,则只有第一个起作用
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
// 解析获取 propertyName 对应的 value值,propertyName 及其 value值会被封装到
// PropertyValue 对象中,然后 set 到 BeanDefinition对象中去
Object val = parsePropertyValue(ele, bd, propertyName);
// 根据 property 的 名字propertyName 和 值val 创建 PropertyValue实例
PropertyValue pv = new PropertyValue(propertyName, val);
// 解析 <meta> 元素
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
// 为当前的 BeanDefinition对象设置 propertyValues 属性值
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
/**
* 解析获取 <property> 元素的属性值 value
*/
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = (propertyName != null) ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element";
// 获取 <property> 的所有子元素,只能是其中一种类型:ref,value,list 等
NodeList nl = ele.getChildNodes();
Element subElement = null;
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 如果子元素不是 description 和 meta 属性
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
!nodeNameEquals(node, META_ELEMENT)) {
// Child element is what we're looking for.
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {// 当前 <property> 元素包含有子元素
subElement = (Element) node;
}
}
}
// 判断 property 的属性值是 ref 还是 value,不允许既是 ref 又是 value
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null)) {
error(elementName +
" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
// 如果属性是 ref,创建一个 ref 的数据对象 RuntimeBeanReference
// 这个对象封装了 ref 信息
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
// 一个指向运行时所依赖对象的引用
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
// 设置这个 ref 的数据对象是被当前的 property 对象所引用
ref.setSource(extractSource(ele));
return ref;
}
// 如果属性是 value,创建一个 value 的数据对象 TypedStringValue
// 这个对象封装了 value 信息
else if (hasValueAttribute) {
// 一个持有 String 类型值的对象
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
// 设置这个 value 数据对象是被当前的 property 对象所引用
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
// 如果当前 <property> 元素还有子元素
else if (subElement != null) {
// 解析 <property> 的子元素
return parsePropertySubElement(subElement, bd);
}
else {
// propery 属性中既不是 ref,也不是 value 属性,解析出错返回 null
error(elementName + " must specify a ref or value", ele);
return null;
}
}
/**
* 解析 <property> 元素中 ref,value 或者集合等子元素
*/
public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
return parsePropertySubElement(ele, bd, null);
}
public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
// 如果 <property> 没有使用 Spring 默认的命名空间,则使用用户自定义的规则解析
// 内嵌元素
if (!isDefaultNamespace(ele)) {
return parseNestedCustomElement(ele, bd);
}
// 如果子元素是 bean,则使用解析 <Bean> 元素的方法解析
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
}
// 如果子元素是 ref,ref 中只能有以下 3 个属性:bean、local、parent
else if (nodeNameEquals(ele, REF_ELEMENT)) {
// 获取 <property> 元素中的 bean 属性值,引用其他解析的 Bean 的名称
// 可以不再同一个 Spring 配置文件中,具体请参考 Spring 对 ref 的配置规则
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
// 获取 <property> 元素中的 local 属性值,引用同一个 Xml 文件中配置
// 的 Bean 的 id,local 和 ref 不同,local 只能引用同一个配置文件中的 Bean
refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
if (!StringUtils.hasLength(refName)) {
// 获取 <property> 元素中 parent 属性值,引用父级容器中的 Bean
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean', 'local' or 'parent' is required for <ref> element", ele);
return null;
}
}
}
// 没有配置 ref 的目标属性值
if (!StringUtils.hasText(refName)) {
error("<ref> element contains empty target attribute", ele);
return null;
}
// 创建 ref 类型数据,指向被引用的对象
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
// 设置引用类型值是被当前子元素所引用
ref.setSource(extractSource(ele));
return ref;
}
// 如果子元素是 <idref>,使用解析 ref 元素的方法解析
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
return parseIdRefElement(ele);
}
// 如果子元素是 <value>,使用解析 value 元素的方法解析
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultValueType);
}
//如果子元素是 null,为 <property> 设置一个封装 null 值的字符串数据
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
TypedStringValue nullHolder = new TypedStringValue(null);
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
// 如果子元素是 <array>,使用解析 array 集合子元素的方法解析
else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
// 如果子元素是 <list>,使用解析 list 集合子元素的方法解析
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
return parseListElement(ele, bd);
}
// 如果子元素是 <set>,使用解析 set 集合子元素的方法解析
else if (nodeNameEquals(ele, SET_ELEMENT)) {
return parseSetElement(ele, bd);
}
// 如果子元素是 <map>,使用解析 map 集合子元素的方法解析
else if (nodeNameEquals(ele, MAP_ELEMENT)) {
return parseMapElement(ele, bd);
}
// 如果子元素是 <props>,使用解析 props 集合子元素的方法解析
else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
return parsePropsElement(ele);
}
// 既不是 ref,又不是 value,也不是集合,则子元素配置错误,返回 null
else {
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
/**
* 解析 <list> 集合子元素
*/
public List parseListElement(Element collectionEle, BeanDefinition bd) {
// 获取 <list> 元素中的 value-type 属性,即获取集合元素的数据类型
String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
// 获取 <list> 集合元素中的所有子节点
NodeList nl = collectionEle.getChildNodes();
// Spring 中将 List 封装为 ManagedList
ManagedList<Object> target = new ManagedList<Object>(nl.getLength());
target.setSource(extractSource(collectionEle));
// 设置集合目标数据类型
target.setElementTypeName(defaultElementType);
target.setMergeEnabled(parseMergeAttribute(collectionEle));
// 具体的 <list> 元素解析
parseCollectionElements(nl, target, bd, defaultElementType);
return target;
}
/**
* 具体解析 <list> 集合元素,<array>、<list> 和 <set> 都使用该方法解析
*/
protected void parseCollectionElements(NodeList elementNodes, Collection<Object> target,
BeanDefinition bd, String defaultElementType) {
// 遍历集合所有节点
for (int i = 0; i < elementNodes.getLength(); i++) {
Node node = elementNodes.item(i);
// 节点不是 description 节点
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
// 将解析的元素加入集合中,递归调用下一个子元素
target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
}
}
}
|