PropertyUtil
1.copyProperties(Object, Object, String…)
将 fromObj 中的全部或者一组属性的值,复制到 toObj 对象中.
注意点:
- 如果 toObj 是null,抛出
NullPointerException
- 如果 fromObj 是null,抛出
NullPointerException
- 对于Date类型,不需要先注册converter
- 这种copy都是
浅拷贝
,复制后的2个Bean的同一个属性可能拥有同一个对象的ref,这个在使用时要小心,特别是对于属性为自定义类的情况 .使用示例:
User oldUser = new User();
oldUser.setId(5L);
oldUser.setMoney(new BigDecimal(500000));
oldUser.setDate(new Date());
oldUser.setNickName(ConvertUtil.toArray("feilong", "飞天奔月", "venusdrogon"));
User newUser = new User();
PropertyUtil.copyProperties(newUser, oldUser, "date", "money", "nickName");
LOGGER.debug(JsonUtil.format(newUser));
返回:
{
"date": "2015-09-06 13:27:43",
"id": 0,
"nickName": [
"feilong",
"飞天奔月",
"venusdrogon"
],
"age": 0,
"name": "feilong",
"money": 500000,
"userInfo": {"age": 0}
}
重构:对于以下代码:
private ContactCommand toContactCommand(ShippingInfoSubForm shippingInfoSubForm){
ContactCommand contactCommand = new ContactCommand();
contactCommand.setCountryId(shippingInfoSubForm.getCountryId());
contactCommand.setProvinceId(shippingInfoSubForm.getProvinceId());
contactCommand.setCityId(shippingInfoSubForm.getCityId());
contactCommand.setAreaId(shippingInfoSubForm.getAreaId());
contactCommand.setTownId(shippingInfoSubForm.getTownId());
return contactCommand;
}
可以重构成:
private ContactCommand toContactCommand(ShippingInfoSubForm shippingInfoSubForm){
ContactCommand contactCommand = new ContactCommand();
PropertyUtil.copyProperties(contactCommand, shippingInfoSubForm, "countryId", "provinceId", "cityId", "areaId", "townId");
return contactCommand;
}
可以看出,代码更精简,目的性更明确
BeanUtils.copyProperties(Object, Object)与 PropertyUtils.copyProperties(Object, Object)区别
BeanUtils
提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而PropertyUtils
不支持这个功能,但是速度会更快一些.commons-beanutils
v1.9.0以前的版本BeanUtils
不允许对象的属性值为 null,PropertyUtils
可以拷贝属性值 null的对象.(注:
commons-beanutils
v1.9.0+修复了这个情况,BeanUtilsBean.copyProperties()
no longer throws aConversionException
for null properties of certain data types),具体参阅commons-beanutils的 RELEASE-NOTES.txt相比较直接调用PropertyUtils.copyProperties(Object, Object)
的优点:将
checkedException
异常转成了BeanOperationException
RuntimeException
,因为通常copy的时候出现了checkedException
,也是普普通通记录下log,没有更好的处理方式- 支持
includePropertyNames
参数,允许针对性copy 个别属性 - 更多,更容易理解的的javadoc
2.describe(Object, String…)
返回一个 bean中指定属性 propertyNames
可读属性,并将属性名/属性值放入一个 LinkedHashMap
中.
示例:**场景:** 取到user bean里面所有的属性成map
User user = new User();
user.setId(5L);
user.setDate(new Date());
LOGGER.debug(JsonUtil.format(PropertyUtil.describe(user));
返回:
{
"id": 5,
"name": "feilong",
"age": null,
"date": "2016-07-13 22:18:26"
}
场景: 提取user bean "date"和 "id"属性:
User user = new User();
user.setId(5L);
user.setDate(new Date());
LOGGER.debug(JsonUtil.format(PropertyUtil.describe(user, "date", "id"));
返回的结果,按照指定参数名称顺序:
{
"date": "2016-07-13 22:21:24",
"id": 5
}
说明:
- 另外还有一个名为class的属性,属性值是Object的类名,事实上class是
java.lang.Object
的一个属性 - 如果
propertyNames
是null或者 empty,那么获取所有属性的值 map的key按照
propertyNames
的顺序原理:取到bean class的
java.beans.PropertyDescriptor
数组- 循环,找到
java.beans.PropertyDescriptor.getReadMethod()
- 将 name and
org.apache.commons.beanutils.PropertyUtilsBean.getProperty(Object, String)
设置到map中
3.findValueOfType(Object, Class<T>)
从指定的 obj中,查找指定类型 toBeFindedClassType
的值.
说明:
- 如果
ClassUtil.isInstance(obj, toBeFindedClassType)
直接返回 findValue - 不支持obj是
isPrimitiveOrWrapper
,CharSequence
,Collection
,Map
类型,自动过滤 - 调用
PropertyUtil.describe(Object, String)
再递归查找 - 目前暂不支持从集合里面找到指定类型的值,如果你有相关需求,可以调用
"org.springframework.util.CollectionUtils#findValueOfType(Collection, Class)"
示例:**场景:** 从User中找到UserInfo类型的值
User user = new User();
user.setId(5L);
user.setDate(new Date());
user.getUserInfo().setAge(28);
LOGGER.info(JsonUtil.format(PropertyUtil.findValueOfType(user, UserInfo.class)));
返回:
{"age": 28}
4.getProperty(Object, String)
使用 PropertyUtils.getProperty(Object, String)
从指定bean对象中取得指定属性名称的值.
说明:
- 不会进行类型转换.示例:
场景: 取list中第一个元素的id
User user = new User();
user.setId(5L);
user.setDate(new Date());
List<User> list = toList(user, user, user);
Long id = PropertyUtil.getProperty(list, "[0].id");
返回:
5
5.set
5.1 setProperty(Object, String, Object)
使用 PropertyUtils.setProperty(Object, String, Object)
来设置指定bean对象中的指定属性的值.
说明:
- 不会进行类型转换示例:
User newUser = new User();
PropertyUtil.setProperty(newUser, "name", "feilong");
LOGGER.info(JsonUtil.format(newUser));
返回:
{
"age": 0,
"name": "feilong"
}
注意点:
- 如果 bean 是null,抛出
NullPointerException
- 如果 propertyName 是null,抛出
NullPointerException
- 如果 propertyName 是blank,抛出
IllegalArgumentException
- 如果bean没有传入的 propertyName属性名字,会抛出异常,see setSimpleProperty Line2078,转成 BeanOperationException
- 对于Date类型,不需要先注册converter
5.2 setPropertyIfValueNotNull(Object, String, Object)
如果 null != value,那么才调用 setProperty(Object, String, Object)
.
注意点:
- 如果 bean 是null,抛出
NullPointerException
- 如果 propertyName 是null,抛出
NullPointerException
- 如果 propertyName 是blank,抛出
IllegalArgumentException
- 如果bean没有传入的 propertyName属性名字,会抛出异常,see
PropertyUtilsBean.setSimpleProperty(Object, String, Object)
Line2078 - 对于Date类型,不需要先注册converter
5.3 setPropertyIfValueNotNullOrEmpty(Object, String, Object)
如果 value isNotNullOrEmpty,那么才调用 setProperty(Object, String, Object)
.
注意点:
- 如果 bean 是null,抛出
NullPointerException
- 如果 propertyName 是null,抛出
NullPointerException
- 如果 propertyName 是blank,抛出
IllegalArgumentException
- 如果bean没有传入的 propertyName属性名字,会抛出异常,see
PropertyUtilsBean.setSimpleProperty(Object, String, Object)
Line2078 - 对于Date类型,不需要先注册converter