matlab 表示键值对,Spring 属性注入(四)属性键值对 - PropertyValue

Spring 属性注入(四)属性键值对 - PropertyValue

PropertyValue 和 PropertyValues 都位于 org.springframework.beans 包下,是 bean 属性键值对的封装,缓存了对 key-value 解析相关的信息,避免重复解析。

一、PropertyValue

fbb0bdaacafa55a2c7bef3109c945a9c.png

AttributeAccessor 可以访问对象的属性或将属性附加到对象上。

BeanMetadataElement 持有属性信息的对象。

BeanMetadataAttributeAccessor 实现了 AttributeAccessor 和 BeanMetadataElement 两个接口,属性为 BeanMetadataAttribute 对象。

PropertyValue 属性键值对。

有一点不太明白 PropertyValue 表示一个属性键值对,PropertyValues 表示多个属性键值对,那 PropertyValue 为什么还要继承 AttributeAccessor 接口,AttributeAccessor 可以对多个属性进行管理。

1.1 AttributeAccessor

public interface AttributeAccessor {

// 对属性进行增删改查

void setAttribute(String name, @Nullable Object value);

Object getAttribute(String name);

Object removeAttribute(String name);

boolean hasAttribute(String name);

String[] attributeNames();

}

AttributeAccessor 接口的实现类为 AttributeAccessorSupport,在这个类中维护一个 Map attributes = new LinkedHashMap<>(),对属性进行增删改查。

1.2 BeanMetadataElement

public interface BeanMetadataElement {

Object getSource();

}

BeanMetadataAttributeAccessor 的实现了 AttributeAccessor 和 BeanMetadataElement 两个接口,内部维护的是 键值对,BeanMetadataAttribute 是一个持有属性对和源的对象。

public class BeanMetadataAttribute implements BeanMetadataElement {

// 属性 key - value

private final String name;

private final Object value;

// 属性所属的对象

private Object source;

}

1.3 PropertyValue

PropertyValue 缓存了对 key-value 解析相关的信息,避免重复解析。如 AbstractNestablePropertyAccessor#processLocalProperty 进行属性注入时,会判断是否需要对属性值进行类型转换。相关字段如下:

// 1.1 属性名称

private final String name;

// 1.1 属性值

private final Object value;

// 2.1 属性值是否为 Optional

private boolean optional = false;

// 2.2 属性值是否已经进行了类型转换

private boolean converted = false;

// 2.3 类型转换后的属性值

private Object convertedValue;

// 3.1 属性值是否需要进行类型转换,如果转换前后对象都是同一个,说明不用转换

volatile Boolean conversionNecessary;

// 3.2 缓存解析后的属性名称,如 attr['info']['name']

transient volatile Object resolvedTokens;

直接设置 convertedValue 值时 converted = true。

public synchronized void setConvertedValue(@Nullable Object value) {

this.converted = true;

this.convertedValue = value;

}

二、PropertyValues

aa91ffdf14c044416a17a3ac16d4abbd.png

PropertyValues 表示多个属性键值对,接口如下:

public interface PropertyValues extends Iterable {

// @since 5.1

default Iterator iterator() {

return Arrays.asList(getPropertyValues()).iterator();

}

PropertyValue[] getPropertyValues();

PropertyValue getPropertyValue(String propertyName);

boolean contains(String propertyName);

boolean isEmpty();

// old 和当前的对比,返回当前有而 old 没有的元素

PropertyValues changesSince(PropertyValues old);

}

PropertyValues 的默认实现为 MutablePropertyValues,内部也是维护了一个 List propertyValueList 集合。MutablePropertyValues 会将属性值转换成 PropertyValue 进行存储。

(1) 属性

private final List propertyValueList;

// 已经解析过的 PropertyValue

private Set processedProperties;

private volatile boolean converted = false;

(2) addPropertyValues

可以将 Map、PropertyValue 属性添加到集合中,MutablePropertyValues 统一封装成 PropertyValue 进行存储。

public MutablePropertyValues addPropertyValues(@Nullable Map, ?> other) {

if (other != null) {

other.forEach((attrName, attrValue) -> addPropertyValue(

new PropertyValue(attrName.toString(), attrValue)));

}

return this;

}

// 所有类型的属性键值对都会转换成 PropertyValue 后进行存储

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;

}

}

this.propertyValueList.add(pv);

return this;

}

注意如果属性值是 Mergeable 类型会先合并,代码如下:

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;

}

Mergeable 的子类有 ManagedSet、ManagedList、ManagedMap、ManagedProperties、ManagedArray,合并也很简单,以 ManagedList 为例:

public List merge(@Nullable Object parent) {

List merged = new ManagedList<>();

merged.addAll((List) parent);

merged.addAll(this);

return merged;

}

(3) getPropertyValue

public PropertyValue getPropertyValue(String propertyName) {

for (PropertyValue pv : this.propertyValueList) {

if (pv.getName().equals(propertyName)) {

return pv;

}

}

return null;

}

(4) changesSince

查找相对 old 发生变化的所有元素。

@Override

public PropertyValues changesSince(PropertyValues old) {

MutablePropertyValues changes = new MutablePropertyValues();

// 1. 返回空集合

if (old == this) {

return changes;

}

// 2. 返回 propertyValueList 中有而 old 没有的元素集合

for (PropertyValue newPv : this.propertyValueList) {

PropertyValue pvOld = old.getPropertyValue(newPv.getName());

if (pvOld == null || !pvOld.equals(newPv)) {

changes.addPropertyValue(newPv);

}

}

return changes;

}

每天用心记录一点点。内容也许不重要,但习惯很重要!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值