PropertyUtil

PropertyUtil

1.copyProperties(Object, Object, String…)

将 fromObj 中的全部或者一组属性的值,复制到 toObj 对象中.

注意点:

  • 如果 toObj 是null,抛出 NullPointerException
  • 如果 fromObj 是null,抛出 NullPointerException
  • 对于Date类型,不需要先注册converter
  • 这种copy都是 浅拷贝,复制后的2个Bean的同一个属性可能拥有同一个对象的ref,这个在使用时要小心,特别是对于属性为自定义类的情况 .使用示例:
  1. User oldUser = new User();
  2. oldUser.setId(5L);
  3. oldUser.setMoney(new BigDecimal(500000));
  4. oldUser.setDate(new Date());
  5. oldUser.setNickName(ConvertUtil.toArray("feilong", "飞天奔月", "venusdrogon"));
  6. User newUser = new User();
  7. PropertyUtil.copyProperties(newUser, oldUser, "date", "money", "nickName");
  8. LOGGER.debug(JsonUtil.format(newUser));

返回:

  1. {
  2. "date": "2015-09-06 13:27:43",
  3. "id": 0,
  4. "nickName": [
  5. "feilong",
  6. "飞天奔月",
  7. "venusdrogon"
  8. ],
  9. "age": 0,
  10. "name": "feilong",
  11. "money": 500000,
  12. "userInfo": {"age": 0}
  13. }

重构:对于以下代码:

  1. private ContactCommand toContactCommand(ShippingInfoSubForm shippingInfoSubForm){
  2. ContactCommand contactCommand = new ContactCommand();
  3. contactCommand.setCountryId(shippingInfoSubForm.getCountryId());
  4. contactCommand.setProvinceId(shippingInfoSubForm.getProvinceId());
  5. contactCommand.setCityId(shippingInfoSubForm.getCityId());
  6. contactCommand.setAreaId(shippingInfoSubForm.getAreaId());
  7. contactCommand.setTownId(shippingInfoSubForm.getTownId());
  8. return contactCommand;
  9. }

可以重构成:

  1. private ContactCommand toContactCommand(ShippingInfoSubForm shippingInfoSubForm){
  2. ContactCommand contactCommand = new ContactCommand();
  3. PropertyUtil.copyProperties(contactCommand, shippingInfoSubForm, "countryId", "provinceId", "cityId", "areaId", "townId");
  4. return contactCommand;
  5. }

可以看出,代码更精简,目的性更明确

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

  1. User user = new User();
  2. user.setId(5L);
  3. user.setDate(new Date());
  4. LOGGER.debug(JsonUtil.format(PropertyUtil.describe(user));

返回:

  1. {
  2. "id": 5,
  3. "name": "feilong",
  4. "age": null,
  5. "date": "2016-07-13 22:18:26"
  6. }

场景: 提取user bean "date"和 "id"属性:

  1. User user = new User();
  2. user.setId(5L);
  3. user.setDate(new Date());
  4. LOGGER.debug(JsonUtil.format(PropertyUtil.describe(user, "date", "id"));

返回的结果,按照指定参数名称顺序:

  1. {
  2. "date": "2016-07-13 22:21:24",
  3. "id": 5
  4. }

说明:

  • 另外还有一个名为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类型的值
  1. User user = new User();
  2. user.setId(5L);
  3. user.setDate(new Date());
  4. user.getUserInfo().setAge(28);
  5. LOGGER.info(JsonUtil.format(PropertyUtil.findValueOfType(user, UserInfo.class)));

返回:

  1. {"age": 28}

4.getProperty(Object, String)

使用 PropertyUtils.getProperty(Object, String) 从指定bean对象中取得指定属性名称的值.

说明:

  • 不会进行类型转换.示例:

场景: 取list中第一个元素的id

  1. User user = new User();
  2. user.setId(5L);
  3. user.setDate(new Date());
  4. List<User> list = toList(user, user, user);
  5. Long id = PropertyUtil.getProperty(list, "[0].id");

返回:

  1. 5

5.set

5.1 setProperty(Object, String, Object)

使用 PropertyUtils.setProperty(Object, String, Object) 来设置指定bean对象中的指定属性的值.

说明:

  • 不会进行类型转换示例:
  1. User newUser = new User();
  2. PropertyUtil.setProperty(newUser, "name", "feilong");
  3. LOGGER.info(JsonUtil.format(newUser));

返回:

  1. {
  2. "age": 0,
  3. "name": "feilong"
  4. }

注意点:

  • 如果 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