Skip to content

Commit 08485dd

Browse files
committed
doc: Spring-Property
1 parent c3847d9 commit 08485dd

5 files changed

Lines changed: 393 additions & 0 deletions

File tree

Lines changed: 393 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,393 @@
1+
# Spring Property
2+
3+
- Author: [HuiFer](https://github.com/huifer)
4+
- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read)
5+
6+
7+
- 相关类
8+
- `org.springframework.beans.PropertyValues`
9+
- `org.springframework.beans.PropertyValue`
10+
- `org.springframework.beans.MutablePropertyValues`
11+
12+
13+
14+
15+
- 类图如下
16+
17+
![images](/images/spring/PropertyValues.png)
18+
19+
20+
21+
- 在 Spring IoC 中,**非Web工程**,使用 xml 或者注解进行配置主要使用到的是 `PropertyValues``PropertyValue``MutablePropertyValues` 三个
22+
23+
其中 `PropertyValues` 是继承迭代器,具体实现在`MutablePropertyValues` 他们处理的对象是`PropertyValues`
24+
25+
关系就是这样.
26+
27+
28+
29+
- 开始类的解析了
30+
31+
32+
33+
34+
35+
## PropertyValue
36+
37+
- `org.springframework.beans.PropertyValue`
38+
39+
- 类图
40+
41+
![](/images/spring/PropertyValue.png)
42+
43+
- 这个类暂时只关注两个属性
44+
45+
1. name: 属性名称
46+
2. value: 属性值
47+
48+
对应标签`<property name="age" value="30"/>`
49+
50+
属性值一一对应填入.
51+
52+
53+
54+
55+
56+
## MutablePropertyValues
57+
58+
- `org.springframework.beans.MutablePropertyValues`
59+
60+
- 属性
61+
1. `propertyValueList`:属性列表, key:参数名称,value:具体数据
62+
2. `processedProperties`: 已经处理的属性名称
63+
3. `converted`: 是否转换
64+
65+
66+
67+
```java
68+
public class MutablePropertyValues implements PropertyValues, Serializable {
69+
/**
70+
* 属性列表, key:参数名称,value:具体数据
71+
*/
72+
private final List<PropertyValue> propertyValueList;
73+
74+
/**
75+
* 已经处理的属性名称
76+
*/
77+
@Nullable
78+
private Set<String> processedProperties;
79+
80+
/**
81+
* 是否转换
82+
*/
83+
private volatile boolean converted = false;
84+
}
85+
```
86+
87+
88+
89+
### 构造器
90+
91+
- `MutablePropertyValues` 的一个构造器. 其他构造器的方式原理实现差不多. 核心是将构造参数转换成`PropertyValue`对象在放入`propertyValueList`
92+
93+
```java
94+
public MutablePropertyValues(@Nullable PropertyValues original) {
95+
// We can optimize this because it's all new:
96+
// There is no replacement of existing property values.
97+
if (original != null) {
98+
// 从列表中获取所有可能指
99+
PropertyValue[] pvs = original.getPropertyValues();
100+
this.propertyValueList = new ArrayList<>(pvs.length);
101+
for (PropertyValue pv : pvs) {
102+
// 循环插入 property values
103+
this.propertyValueList.add(new PropertyValue(pv));
104+
}
105+
}
106+
else {
107+
this.propertyValueList = new ArrayList<>(0);
108+
}
109+
}
110+
```
111+
112+
113+
114+
115+
116+
117+
118+
### PropertyValue 的构造方法
119+
120+
121+
122+
```JAVA
123+
public PropertyValue(PropertyValue original) {
124+
Assert.notNull(original, "Original must not be null");
125+
this.name = original.getName();
126+
this.value = original.getValue();
127+
this.optional = original.isOptional();
128+
this.converted = original.converted;
129+
this.convertedValue = original.convertedValue;
130+
this.conversionNecessary = original.conversionNecessary;
131+
this.resolvedTokens = original.resolvedTokens;
132+
setSource(original.getSource());
133+
copyAttributesFrom(original);
134+
}
135+
136+
```
137+
138+
139+
140+
- 除了最后一行是一个复杂调用. 前面几行代码都是属性赋值操作.
141+
- 最后一行代码会调用`AttributeAccessor`接口上的方法.
142+
143+
144+
145+
146+
147+
148+
149+
## AttributeAccessor
150+
151+
- `org.springframework.core.AttributeAccessor`
152+
153+
- 完整的方法列表及作用注释
154+
155+
```java
156+
public interface AttributeAccessor {
157+
158+
/**
159+
* 设置属性值
160+
* @param name 属性值名称
161+
* @param value 属性值
162+
*/
163+
void setAttribute(String name, @Nullable Object value);
164+
165+
/**
166+
* 通过属性名称获取属性值
167+
*
168+
* @param name 属性值名称
169+
* @return 属性值
170+
*/
171+
@Nullable
172+
Object getAttribute(String name);
173+
174+
/**
175+
* 移除指定属性名称的值,返回移除的属性值
176+
*
177+
* @param name 属性值名称
178+
* @return 移除的属性值
179+
*/
180+
@Nullable
181+
Object removeAttribute(String name);
182+
183+
/**
184+
* 是否包含属性名称
185+
* @param 属性名称
186+
*/
187+
boolean hasAttribute(String name);
188+
189+
/**
190+
* 属性名称列表
191+
*/
192+
String[] attributeNames();
193+
194+
}
195+
```
196+
197+
198+
199+
200+
201+
- 回到`org.springframework.core.AttributeAccessorSupport#copyAttributesFrom`方法
202+
203+
204+
205+
206+
207+
```java
208+
protected void copyAttributesFrom(AttributeAccessor source) {
209+
Assert.notNull(source, "Source must not be null");
210+
// 获取属性名称列表
211+
String[] attributeNames = source.attributeNames();
212+
// 循环属性名称列表
213+
for (String attributeName : attributeNames) {
214+
// 设置属性
215+
// name: 属性名称,value: 从入参中获取属性名称对应的属性值
216+
setAttribute(attributeName, source.getAttribute(attributeName));
217+
}
218+
}
219+
```
220+
221+
222+
223+
224+
225+
### setAttribute
226+
227+
- 一个map操作
228+
229+
```java
230+
@Override
231+
public void setAttribute(String name, @Nullable Object value) {
232+
Assert.notNull(name, "Name must not be null");
233+
if (value != null) {
234+
this.attributes.put(name, value);
235+
}
236+
else {
237+
removeAttribute(name);
238+
}
239+
}
240+
```
241+
242+
243+
244+
## addPropertyValue
245+
246+
- `org.springframework.beans.MutablePropertyValues#addPropertyValue(org.springframework.beans.PropertyValue)`
247+
248+
```java
249+
public MutablePropertyValues addPropertyValue(PropertyValue pv) {
250+
// 循环获取 属性对象
251+
for (int i = 0; i < this.propertyValueList.size(); i++) {
252+
// 正在处理的 属性对象
253+
PropertyValue currentPv = this.propertyValueList.get(i);
254+
// 正在处理的属性对象名称和添加的属性对象名称比较
255+
// 如果相同会做一个合并操作
256+
if (currentPv.getName().equals(pv.getName())) {
257+
// 合并属性
258+
pv = mergeIfRequired(pv, currentPv);
259+
// 重新设置
260+
setPropertyValueAt(pv, i);
261+
return this;
262+
}
263+
}
264+
// 放入 list 集合
265+
this.propertyValueList.add(pv);
266+
return this;
267+
}
268+
269+
```
270+
271+
272+
273+
274+
275+
## mergeIfRequired
276+
277+
- `org.springframework.beans.MutablePropertyValues#mergeIfRequired`
278+
279+
280+
281+
- 这段代码会取舍新老数据.
282+
1. 如果是`Mergeable`类型会做合并操作
283+
2. 直接返回新数据
284+
285+
```java
286+
private PropertyValue mergeIfRequired(PropertyValue newPv, PropertyValue currentPv) {
287+
Object value = newPv.getValue();
288+
if (value instanceof Mergeable) {
289+
Mergeable mergeable = (Mergeable) value;
290+
if (mergeable.isMergeEnabled()) {
291+
// 获取合并的结果,放入对象
292+
Object merged = mergeable.merge(currentPv.getValue());
293+
// 创建新的 属性对象
294+
return new PropertyValue(newPv.getName(), merged);
295+
}
296+
}
297+
return newPv;
298+
}
299+
300+
```
301+
302+
303+
304+
- 配合测试代码,跟容易看懂.
305+
306+
```java
307+
@Test
308+
public void testAddOrOverride() {
309+
MutablePropertyValues pvs = new MutablePropertyValues();
310+
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
311+
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
312+
pvs.addPropertyValue(new PropertyValue("age", "50"));
313+
doTestTony(pvs);
314+
PropertyValue addedPv = new PropertyValue("rod", "Rod");
315+
pvs.addPropertyValue(addedPv);
316+
assertThat(pvs.getPropertyValue("rod").equals(addedPv)).isTrue();
317+
PropertyValue changedPv = new PropertyValue("forname", "Greg");
318+
pvs.addPropertyValue(changedPv);
319+
assertThat(pvs.getPropertyValue("forname").equals(changedPv)).isTrue();
320+
}
321+
```
322+
323+
324+
325+
326+
327+
328+
329+
330+
331+
## Mergeable
332+
333+
334+
335+
新的接口`Mergeable`
336+
337+
- `org.springframework.beans.Mergeable`
338+
339+
340+
341+
342+
343+
344+
345+
```java
346+
public interface Mergeable {
347+
348+
/**
349+
* 是否需要合并
350+
*/
351+
boolean isMergeEnabled();
352+
353+
/**
354+
* 合并方法
355+
*/
356+
Object merge(@Nullable Object parent);
357+
358+
}
359+
```
360+
361+
362+
363+
![](/images/spring/Mergeable.png)
364+
365+
366+
367+
- 看一下 List 怎么实现`merge`
368+
369+
370+
371+
```java
372+
@Override
373+
@SuppressWarnings("unchecked")
374+
public List<E> merge(@Nullable Object parent) {
375+
if (!this.mergeEnabled) {
376+
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
377+
}
378+
if (parent == null) {
379+
return this;
380+
}
381+
if (!(parent instanceof List)) {
382+
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
383+
}
384+
List<E> merged = new ManagedList<>();
385+
merged.addAll((List<E>) parent);
386+
merged.addAll(this);
387+
return merged;
388+
}
389+
```
390+
391+
392+
393+
- 在 list 视线中就是讲两个结果合并. 事实上其他的几个都是这个操作. 这里就不贴所有的代码了

images/spring/Mergeable.png

12.9 KB
Loading
99.1 KB
Loading

images/spring/PropertyValue.png

102 KB
Loading

images/spring/PropertyValues.png

39.5 KB
Loading

0 commit comments

Comments
 (0)