当前位置:   article > 正文

改造BeanUtils,优雅实现List数据拷贝

改造BeanUtils,优雅实现List数据拷贝

BeanUtils.copyProperties();确实为我们做了很多事情,虽然不能完美完成深拷贝,但是对于 po、vo、dto 的拷贝已经足够用了。可还是有一些不够完美的地方。

不足几点如下:

. 不能拷贝 list,而拷贝 list 的情况又大量存在,因此会有许多重复代码。

  1. for (S source : sources) {
  2.     T target = new T();
  3.     copyProperties(source, target);
  4.     list.add(target);
  5. }

. 有一些简单的查询,仅仅需要转换一下 vo 也需要 new Vo()。

  1. public Vo findById(Integer id) {
  2.  Vo vo = new Vo();
  3.  Po po = dao.findById(id);
  4.  copyProperties(po, vo);
  5.  return vo;
  6. }

. 这种拷贝方式是没有返回值的,jdk8 支持 stream() 操作之后,支持不是很友好,不方便 lambda 表达式的使用,因此我们决定通过集成 BeanUtils 类,自己造一个方便用的轮子。

使用

我们将新创建一个轮子 BeanConvertUtils,使用如下,当我们要转换 po、vo 时,只需要:

  1. // 使用前
  2. public Vo findById(Integer id) {
  3.  Vo vo = new Vo();
  4.  Po po = dao.findById(id);
  5.  copyProperties(po, vo);
  6.  return vo;
  7. }
  8. // 使用后
  9. public Vo findById(Integer id) {
  10.  return BeanConvertUtils.converTo(dao.findById(id), Vo::new);
  11. }
  12. // 使用后,通过lambda表达式特殊处理个别字段
  13. public Vo findById(Integer id) {
  14.  return BeanConvertUtils.converTo(dao.findById(id), Vo::new
  15.   (s, t) -> t.setName(s.getName))
  16.  );
  17. }

当我们要拷贝 list 的时候也很简单:

  1. // 使用前
  2. public List<Vo> findAll() {
  3.  List<Vo> vos = new ArrayList();
  4.  List<Po> pos = dao.findAll();
  5.  for (Po po : Pos) {
  6.      Vo vo = new Vo();
  7.      BeanUtis.copyProperties(po, vo);
  8.      vos.add(vo);
  9.     }
  10.  return vos;
  11. }
  12. // 使用后
  13. public List<Vo> findAll() {
  14.  return BeanConvertUtils.converToList(dao.findAll(), Vo::new)
  15. }
  16. // 同样支持自定义lambda
  17. public List<Vo> findAll() {
  18.  return BeanConvertUtils.converToList(dao.findAll(), Vo::new,
  19.   (s, t) -> t.setName(s.getName))
  20.  )
  21. }

代码如下

  1. /**
  2.  * 转换对象工具
  3.  *
  4.  * @author bugpool
  5.  */
  6. public class BeanConvertUtils extends BeanUtils {
  7.     public static <S, T> T convertTo(S source, Supplier<T> targetSupplier) {
  8.         return convertTo(source, targetSupplier, null);
  9.     }
  10.     /**
  11.      * 转换对象
  12.      *
  13.      * @param source         源对象
  14.      * @param targetSupplier 目标对象供应方
  15.      * @param callBack       回调方法
  16.      * @param <S>            源对象类型
  17.      * @param <T>            目标对象类型
  18.      * @return 目标对象
  19.      */
  20.     public static <S, T> T convertTo(S source, Supplier<T> targetSupplier, ConvertCallBack<S, T> callBack) {
  21.         if (null == source || null == targetSupplier) {
  22.             return null;
  23.         }
  24.         T target = targetSupplier.get();
  25.         copyProperties(source, target);
  26.         if (callBack != null) {
  27.             callBack.callBack(source, target);
  28.         }
  29.         return target;
  30.     }
  31.     public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier) {
  32.         return convertListTo(sources, targetSupplier, null);
  33.     }
  34.     /**
  35.      * 转换对象
  36.      *
  37.      * @param sources        源对象list
  38.      * @param targetSupplier 目标对象供应方
  39.      * @param callBack       回调方法
  40.      * @param <S>            源对象类型
  41.      * @param <T>            目标对象类型
  42.      * @return 目标对象list
  43.      */
  44.     public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier, ConvertCallBack<S, T> callBack) {
  45.         if (null == sources || null == targetSupplier) {
  46.             return null;
  47.         }
  48.         List<T> list = new ArrayList<>(sources.size());
  49.         for (S source : sources) {
  50.             T target = targetSupplier.get();
  51.             copyProperties(source, target);
  52.             if (callBack != null) {
  53.                 callBack.callBack(source, target);
  54.             }
  55.             list.add(target);
  56.         }
  57.         return list;
  58.     }
  59.     /**
  60.      * 回调接口
  61.      *
  62.      * @param <S> 源对象类型
  63.      * @param <T> 目标对象类型
  64.      */
  65.     @FunctionalInterface
  66.     public interface ConvertCallBack<S, T> {
  67.         void callBack(S t, T s);
  68.     }
  69. }

性能

由于只是 BeanUtils 的一个封装,跟原来的代码性能几乎差不多,如果要说差一点也没错,毕竟多了一层函数堆栈的调用,但是基本可以忽略不计。主要的性能还是由 BeanUtils 决定。

提醒

不知道大家对这个 BeanConvertUtils 工具类感觉怎么样,自己在项目中倒是大量使用,也很方便。

但是有两点要提醒:

  • 此方法依旧不能解决深层次的深拷贝问题,详细的可以 google 一下 BeanUtils 的深拷贝问题。

  • 如果 source 或者 targetSupplier 只要有一个为 null,本工具类不像 BeanUtils 一样抛出异常,而是返回 null,因为笔者认为调用方如果把 null 进行准换,那就是想转换为 null,为不为空应该由调用方自己负责。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/523690
推荐阅读
相关标签
  

闽ICP备14008679号