source-code-hunter/docs/Spring/clazz/Spring-Property.md

313 lines
7.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Spring Property
- Author: [HuiFer](https://github.com/huifer)
- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read)
- 相关类
- `org.springframework.beans.PropertyValues`
- `org.springframework.beans.PropertyValue`
- `org.springframework.beans.MutablePropertyValues`
- 类图如下
![images](/images/spring/PropertyValues.png)
- 在 Spring IoC 中,**非 Web 工程**,使用 xml 或者注解进行配置主要使用到的是 `PropertyValues` `PropertyValue` `MutablePropertyValues` 三个
其中 `PropertyValues` 是继承迭代器,具体实现在`MutablePropertyValues` 他们处理的对象是`PropertyValues`
关系就是这样.
- 开始类的解析了
## PropertyValue
- `org.springframework.beans.PropertyValue`
- 类图
![](/images/spring/PropertyValue.png)
- 这个类暂时只关注两个属性
1. name: 属性名称
2. value: 属性值
对应标签`<property name="age" value="30"/>`
属性值一一对应填入.
## MutablePropertyValues
- `org.springframework.beans.MutablePropertyValues`
- 属性
1. `propertyValueList`:属性列表, key:参数名称,value:具体数据
2. `processedProperties`: 已经处理的属性名称
3. `converted`: 是否转换
```java
public class MutablePropertyValues implements PropertyValues, Serializable {
/**
* 属性列表, key:参数名称,value:具体数据
*/
private final List<PropertyValue> propertyValueList;
/**
* 已经处理的属性名称
*/
@Nullable
private Set<String> processedProperties;
/**
* 是否转换
*/
private volatile boolean converted = false;
}
```
### 构造器
- `MutablePropertyValues` 的一个构造器. 其他构造器的方式原理实现差不多. 核心是将构造参数转换成`PropertyValue`对象在放入`propertyValueList`中
```java
public MutablePropertyValues(@Nullable PropertyValues original) {
// We can optimize this because it's all new:
// There is no replacement of existing property values.
if (original != null) {
// 从列表中获取所有可能指
PropertyValue[] pvs = original.getPropertyValues();
this.propertyValueList = new ArrayList<>(pvs.length);
for (PropertyValue pv : pvs) {
// 循环插入 property values
this.propertyValueList.add(new PropertyValue(pv));
}
}
else {
this.propertyValueList = new ArrayList<>(0);
}
}
```
### PropertyValue 的构造方法
```JAVA
public PropertyValue(PropertyValue original) {
Assert.notNull(original, "Original must not be null");
this.name = original.getName();
this.value = original.getValue();
this.optional = original.isOptional();
this.converted = original.converted;
this.convertedValue = original.convertedValue;
this.conversionNecessary = original.conversionNecessary;
this.resolvedTokens = original.resolvedTokens;
setSource(original.getSource());
copyAttributesFrom(original);
}
```
- 除了最后一行是一个复杂调用. 前面几行代码都是属性赋值操作.
- 最后一行代码会调用`AttributeAccessor`接口上的方法.
## AttributeAccessor
- `org.springframework.core.AttributeAccessor`
- 完整的方法列表及作用注释
```java
public interface AttributeAccessor {
/**
* 设置属性值
* @param name 属性值名称
* @param value 属性值
*/
void setAttribute(String name, @Nullable Object value);
/**
* 通过属性名称获取属性值
*
* @param name 属性值名称
* @return 属性值
*/
@Nullable
Object getAttribute(String name);
/**
* 移除指定属性名称的值,返回移除的属性值
*
* @param name 属性值名称
* @return 移除的属性值
*/
@Nullable
Object removeAttribute(String name);
/**
* 是否包含属性名称
* @param 属性名称
*/
boolean hasAttribute(String name);
/**
* 属性名称列表
*/
String[] attributeNames();
}
```
- 回到`org.springframework.core.AttributeAccessorSupport#copyAttributesFrom`方法
```java
protected void copyAttributesFrom(AttributeAccessor source) {
Assert.notNull(source, "Source must not be null");
// 获取属性名称列表
String[] attributeNames = source.attributeNames();
// 循环属性名称列表
for (String attributeName : attributeNames) {
// 设置属性
// name: 属性名称,value: 从入参中获取属性名称对应的属性值
setAttribute(attributeName, source.getAttribute(attributeName));
}
}
```
### setAttribute
- 一个 map 操作
```java
@Override
public void setAttribute(String name, @Nullable Object value) {
Assert.notNull(name, "Name must not be null");
if (value != null) {
this.attributes.put(name, value);
}
else {
removeAttribute(name);
}
}
```
## addPropertyValue
- `org.springframework.beans.MutablePropertyValues#addPropertyValue(org.springframework.beans.PropertyValue)`
```java
public MutablePropertyValues addPropertyValue(PropertyValue pv) {
// 循环获取 属性对象
for (int i = 0; i < this.propertyValueList.size(); i++) {
// 正在处理的 属性对象
PropertyValue currentPv = this.propertyValueList.get(i);
// 正在处理的属性对象名称和添加的属性对象名称比较
// 如果相同会做一个合并操作
if (currentPv.getName().equals(pv.getName())) {
// 合并属性
pv = mergeIfRequired(pv, currentPv);
// 重新设置
setPropertyValueAt(pv, i);
return this;
}
}
// 放入 list 集合
this.propertyValueList.add(pv);
return this;
}
```
## mergeIfRequired
- `org.springframework.beans.MutablePropertyValues#mergeIfRequired`
- 这段代码会取舍新老数据.
1. 如果是`Mergeable`类型会做合并操作
2. 直接返回新数据
```java
private PropertyValue mergeIfRequired(PropertyValue newPv, PropertyValue currentPv) {
Object value = newPv.getValue();
if (value instanceof Mergeable) {
Mergeable mergeable = (Mergeable) value;
if (mergeable.isMergeEnabled()) {
// 获取合并的结果,放入对象
Object merged = mergeable.merge(currentPv.getValue());
// 创建新的 属性对象
return new PropertyValue(newPv.getName(), merged);
}
}
return newPv;
}
```
- 配合测试代码,跟容易看懂.
```java
@Test
public void testAddOrOverride() {
MutablePropertyValues pvs = new MutablePropertyValues();
pvs.addPropertyValue(new PropertyValue("forname", "Tony"));
pvs.addPropertyValue(new PropertyValue("surname", "Blair"));
pvs.addPropertyValue(new PropertyValue("age", "50"));
doTestTony(pvs);
PropertyValue addedPv = new PropertyValue("rod", "Rod");
pvs.addPropertyValue(addedPv);
assertThat(pvs.getPropertyValue("rod").equals(addedPv)).isTrue();
PropertyValue changedPv = new PropertyValue("forname", "Greg");
pvs.addPropertyValue(changedPv);
assertThat(pvs.getPropertyValue("forname").equals(changedPv)).isTrue();
}
```
## Mergeable
新的接口`Mergeable`
- `org.springframework.beans.Mergeable`
```java
public interface Mergeable {
/**
* 是否需要合并
*/
boolean isMergeEnabled();
/**
* 合并方法
*/
Object merge(@Nullable Object parent);
}
```
![](/images/spring/Mergeable.png)
- 看一下 List 怎么实现`merge`
```java
@Override
@SuppressWarnings("unchecked")
public List<E> merge(@Nullable Object parent) {
if (!this.mergeEnabled) {
throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'");
}
if (parent == null) {
return this;
}
if (!(parent instanceof List)) {
throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]");
}
List<E> merged = new ManagedList<>();
merged.addAll((List<E>) parent);
merged.addAll(this);
return merged;
}
```
- 在 list 视线中就是讲两个结果合并. 事实上其他的几个都是这个操作. 这里就不贴所有的代码了