Skip to content
This repository has been archived by the owner on Aug 20, 2021. It is now read-only.

PropertyUtil

feilong edited this page Nov 26, 2016 · 1 revision

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 a ConversionException 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)

从指定的 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