# 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 视线中就是讲两个结果合并. 事实上其他的几个都是这个操作. 这里就不贴所有的代码了