学会使用BeanUtils,提高你的开发效率

一、关于BeanUtils

一说到BeanUtils,大家可能不清楚指的哪个BeanUtils。因为它在很多包里面都有,其中挺常用的就是

(1)org.apache.commons.beanutils.BeanUtils

(2)org.springframework.beans.BeanUtils

这两者有什么区别呢?

(1)类的性质不同

apache:

springframework:

apache的是普通类,springframework的是抽象类。

(2)部分相同方法使用方式不同

名字相同,方法名称相同,参数类型和个数都相同,需要实现的功能也一样,但结果大相径庭。

举例:copyProperties (用来在对象之间复制属性值)

apache:

springframework:

眼尖的伙伴已经注意到了,apache的第一个参数是目标对象,第二个是源对象;springframework的第一个参数是源对象,第二个是目标对象。所以大家在开发的时候一定要注意引用的是哪个包。

二、根据已有方法扩展

因为开发的时候有很多类的属性都要重设值,很多时候大把的get、set方法占用你的篇幅与时间,导致拉低开发效率。

所以在此扩展了一些经常用到的方法,供大家参考。

1. 使用org.apache.commons.beanutils.BeanUtils.populate方法

意为将Map中的数据封装到实体类。

扩展之后可以将Map中的数据封装到实体类,并支持日期格式的转换。

  /**
     * 以Map的key和实体的字段名称为对应,复制Map中的值到实体中
     * 
     * @param target 目标对象
     * @param params Map
     * @return T
     */
    public static <T> T copyFields(T target, Map<String, Object> params) {
        if(null == params || params.isEmpty()) {
            return target;
        }
        try {
            org.apache.commons.beanutils.BeanUtils.populate(target, params);
        } catch (IllegalAccessException | InvocationTargetException e) {
            LOGGER.error(e.getMessage(), e);
        }
        return target;
    }

 注意:遇到日期类型不能转换,所以需要自己手动注册一个时间转换器。

这里是在静态代码块里面注册的,将格式为yyyy-MM-dd的字符串转换成Date类型。

static {
        // 注册BeanUtils转换器
        ConvertUtils.register(new Converter() {

            @SuppressWarnings("rawtypes")
            public Object convert(Class type, Object value) {

                try {
                    return DateUtils.parseDate(String.valueOf(value), "yyyy-MM-dd");
                } catch (ParseException e) {
                    LOGGER.error(e.getMessage(), e);
                }
                return null;
            }
        }, Date.class);
    }

 2、使用org.springframework.beans.BeanUtils.getPropertyDescriptors方法

意为获取类的属性描述器

扩展之后可以从一个实体中复制非空字段的值到另一个实体中。

/**
     * 以字段名称为关系,从一个实体中复制非空字段的值到另一个实体中
     * 
     * @param target 目标实体
     * @param source 源实体
     * @return T
     */
    public static <T, S> T copyNotNullFields(T target, S source) {
        Map<String, Object> params = getFiledValues(source, o -> (o != null));
        T newTarget = copyFields(target, params);
        return newTarget;
    }

这里可以根据对属性值的判断,将符合条件的属性与其值封装成Map。 

/**
     * 读取实体,以实体字段名为key,值为value,并将满足条件的value封装成一个Map
     * 
     * @param obj 源实体
     * @param predicate 条件
     * @return Map<String, Object>
     */
    public static Map<String, Object> getFiledValues(Object obj, Predicate<Object> predicate) {
        if(null == obj) {
            return Collections.emptyMap();
        }
        Map<String, Object> map = Maps.newHashMap();
        Arrays.asList(org.springframework.beans.BeanUtils.getPropertyDescriptors(obj.getClass())
        .stream()
        .filter(o -> !o.getName().equals("class"))
        .forEach(o -> 
        {
            String propertyName = o.getName();
            Method readMethod = o.getReadMethod();
            try {
                Object propertyValue = readMethod.invoke(obj);
                if(predicate.test(propertyValue)) {
                    map.put(propertyName, propertyValue);
                }
            } catch (IllegalAccessException | IllegalArgumentException |         InvocationTargetException e) {
                LOGGER.error(e.getMessage(), e);
            }
        });
        return map;
    } 

 三、心得

在开发时,如果经常在一些重复性的,且不必要的地方浪费时间时,那就要想一下方法来避免了,因为这会拉低你的开发效率。

首先自己要思考,怎样才能去很好的解决。如果不能解决,那可以参考已有的解决方案(面向各大搜索引擎编程),学习他们解决问题的思路,看自己能不能活学活用。

然后可以对已有的轮子进行一些自己的优化与封装,使得更加的符合自己的业务场景。

posted @ 2020-07-08 08:38  与李  阅读(490)  评论(0编辑  收藏  举报