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

Posted Java知音_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了改造一下 BeanUtils,优雅的实现 List 数据拷贝相关的知识,希望对你有一定的参考价值。

点击关注公众号,实用技术文章及时了解

前言

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

  • 不足:

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

for (S source : sources) 
    T target = new T();
    copyProperties(source, target);
    list.add(target);

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

public Vo findById(Integer id) 
 Vo vo = new Vo();
 Po po = dao.findById(id);
 copyProperties(po, vo);
 return vo;

3.这种拷贝方式是没有返回值的,现在jdk8支持stream()操作之后(参考:Jdk8 Stream),支持不是很友好,不方便lambda表达式的使用

因此我们决定通过集成BeanUtils类,自己造一个方便用的轮子。

使用

我们将新创建一个轮子BeanConvertUtils,使用如下

当我们要转换po、vo时,只需要

// 使用前
public Vo findById(Integer id) 
 Vo vo = new Vo();
 Po po = dao.findById(id);
 copyProperties(po, vo);
 return vo;


// 使用后
public Vo findById(Integer id) 
 return BeanConvertUtils.converTo(dao.findById(id), Vo::new);


// 使用后,通过lambda表达式特殊处理个别字段
public Vo findById(Integer id) 
 return BeanConvertUtils.converTo(dao.findById(id), Vo::new, 
  (s, t) -> t.setName(s.getName))
 );

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

// 使用前
public List<Vo> findAll() 
 List<Vo> vos = new ArrayList();
 List<Po> pos = dao.findAll();
 for (Po po : Pos) 
     Vo vo = new Vo();
     BeanUtis.copyProperties(po, vo);
     vos.add(vo);
    
 return vos;


// 使用后
public List<Vo> findAll() 
 return BeanConvertUtils.converToList(dao.findAll(), Vo::new)


// 同样支持自定义lambda
public List<Vo> findAll() 
 return BeanConvertUtils.converToList(dao.findAll(), Vo::new,
  (s, t) -> t.setName(s.getName))
 )

代码

/**
 * 转换对象工具
 *
 * @author bugpool
 */
public class BeanConvertUtils extends BeanUtils 

    public static <S, T> T convertTo(S source, Supplier<T> targetSupplier) 
        return convertTo(source, targetSupplier, null);
    

    /**
     * 转换对象
     *
     * @param source         源对象
     * @param targetSupplier 目标对象供应方
     * @param callBack       回调方法
     * @param <S>            源对象类型
     * @param <T>            目标对象类型
     * @return 目标对象
     */
    public static <S, T> T convertTo(S source, Supplier<T> targetSupplier, ConvertCallBack<S, T> callBack) 
        if (null == source || null == targetSupplier) 
            return null;
        

        T target = targetSupplier.get();
        copyProperties(source, target);
        if (callBack != null) 
            callBack.callBack(source, target);
        
        return target;
    

    public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier) 
        return convertListTo(sources, targetSupplier, null);
    

    /**
     * 转换对象
     *
     * @param sources        源对象list
     * @param targetSupplier 目标对象供应方
     * @param callBack       回调方法
     * @param <S>            源对象类型
     * @param <T>            目标对象类型
     * @return 目标对象list
     */
    public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier, ConvertCallBack<S, T> callBack) 
        if (null == sources || null == targetSupplier) 
            return null;
        

        List<T> list = new ArrayList<>(sources.size());
        for (S source : sources) 
            T target = targetSupplier.get();
            copyProperties(source, target);
            if (callBack != null) 
                callBack.callBack(source, target);
            
            list.add(target);
        
        return list;
    

    /**
     * 回调接口
     *
     * @param <S> 源对象类型
     * @param <T> 目标对象类型
     */
    @FunctionalInterface
    public interface ConvertCallBack<S, T> 
        void callBack(S t, T s);
    

性能

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

提醒

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

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

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

来源:bugpool.blog.csdn.net/article/details/105620681

推荐

Java面试题宝典

技术内卷群,一起来学习!!

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!

以上是关于改造一下 BeanUtils,优雅的实现 List 数据拷贝的主要内容,如果未能解决你的问题,请参考以下文章

优雅的使用BeanUtils对List集合的操作

如何优雅的实现数据脱敏

优雅对API进行内部升级改造

BeanUtils 如何拷贝 List?

前端虚拟列表的实现原理

策略模式-优雅的改造短信业务模块