在理论的开发中,存在Vo对象,Dao对象,DTO对象的局部属性复制的问题
比拟笨的方法 A.setxxx(B.getXXX),费时又费劲,怎么解决这个问题呢?
举荐应用两种对象属性复制的方法:
对象属性拷贝的两种形式:
1、BeanUtils(留神BeanUtils应用的是spring的Beanutils的)
2、BeanCopier

先筹备三个Vo对象,Dao对象,Dto对象,前面咱们对这三个对象进行拷贝和复制。

@Data@AllArgsConstructorpublic class UserDo {    private int id;    private String userName;    private LocalDateTime gmtBroth;    private BigDecimal balance;}
@Datapublic class UserDto {    private int id;    private String userName;}
@Data@AllArgsConstructor@NoArgsConstructorpublic class UserVo {    private int id;    private String userName;    private String gmtBroth;    private String agevo;}

第一种形式应用BeanUtils进行拷贝

import org.springframework.beans.BeanUtils;@Slf4jpublic class BeanCopyTest {     public static void main(String[] args) {    UserDo userDo=new UserDo(1,"sunyuhau", LocalDateTime.now(),new BigDecimal(100L));    log.info("拷贝前=="+userDo);    UserVo userVo=new UserVo();    BeanUtils.copyProperties(userDo,userVo);    log.info("拷贝后==="+userVo);    }}

输入后果为:

然而这种办法耗时比拟长,线上有点不能满足需要。所以引出了第二种计划:
BeanCopier

        long startTime2=System.currentTimeMillis();        UserDo userDo1=DataUtil.createData();        log.info("拷贝前 userDo1:{}",userDo1);        //将userDo拷贝到userdto,false代表是不应用自定义转化器        BeanCopier beanCopier=BeanCopier.create(UserDo.class,UserDto.class,false);        UserDto userDto=new UserDto();        //不应用conberter形式,仅对两个bean对象属性名和类型完全相同的变量进行拷贝。        beanCopier.copy(userDo1,userDto,null);        log.info("拷贝后 :userDto:{}",userDto);        log.info("耗时:"+(System.currentTimeMillis()-startTime2));

BeanCopier 有两种形式,一个是conberter,一个是不应用自定义的conberter,下面的不应用自定义器的。

long startTime3=System.currentTimeMillis();        UserDo userDo2=DataUtil.createData();        log.info("拷贝前:{}",userDo2);        BeanCopier.create(UserDo.class,UserVo.class,true);        UserDo userDo3=DataUtil.createData();        log.info("拷贝前:userDo:{}",userDo3);        BeanCopier beanCopier1 = BeanCopier.create(UserDo.class, UserVo.class, true);        UserConverter userConverter=new UserConverter();        UserVo uservo3=new UserVo();        beanCopier1.copy(userDo3,uservo3,userConverter);        log.info("拷贝后==userDo:{}",uservo3);        log.info("耗时3:"+(System.currentTimeMillis()-startTime3));
/** * 自定义的user对象的转化器 * 一旦应用converter,BeanCopier只应用converter定义的规定去拷贝,所以在convert()办法中要思考所有的属性 * 并且converter会是对象拷贝速度变慢。 * */public class UserConverter implements Converter {    DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");    @Override    public Object convert(Object o, Class aClass, Object o1) {        if(o instanceof Integer){            return o;        }else if(o instanceof LocalDateTime){            LocalDateTime date=(LocalDateTime)o;            return dateTimeFormatter.format(date);        }else if(o instanceof BigDecimal){            BigDecimal bigDecimal=(BigDecimal)o;            return bigDecimal.toPlainString();        }        return o;    }}

不论使不应用自定义的转化器,都有还有一个弊病,就是每次都初始化 BeanCopier beanCopier=BeanCopier.create(UserDo.class,UserDto.class,false);
BeanCopier beanCopier1 = BeanCopier.create(UserDo.class, UserVo.class, true);
这个点是不必须的。所以能够将这个初始化到内存中,这样就没有必要每次都生成 BeanCopier。
具体的做法如下:

import lombok.extern.slf4j.Slf4j;import org.springframework.cglib.beans.BeanCopier;import java.util.ArrayList;import java.util.List;import java.util.concurrent.ConcurrentHashMap;@Slf4jpublic  class BeanCopierWithCacheUtil {    private static  ConcurrentHashMap<String,BeanCopier> BEAN_COPIERS = new ConcurrentHashMap<>() ;    static void beanCopierWithCache() {        List<UserDo> userDOList = DataUtil.createDataList(10000);        long start = System.currentTimeMillis();        List<UserDto> userDtos = new ArrayList<>();        userDOList.forEach(userDo -> {            UserDto userDTO = new UserDto();            //将userDo对象的参数,复制到userDTO对象            copy(userDo, userDTO);            userDtos.add(userDTO);        });        log.info("BeanCopier 加缓存后 costTime: {}ms", System.currentTimeMillis() - start);    }    /**     * 将不必类型转化的copier = BeanCopier.create(srcObj.getClass(), destObj.getClass(), false) 放入内存     * 第一次初始化的时候将BeanCopier,初始到内存中,下次再次应用时。间接应用。     * @param srcObj     * @param destObj     */    public static void copy(Object srcObj, Object destObj) {        String key = genKey(srcObj.getClass(), destObj.getClass());        BeanCopier copier = null;        if (!BEAN_COPIERS.containsKey(key)) {            copier = BeanCopier.create(srcObj.getClass(), destObj.getClass(), false);            BEAN_COPIERS.put(key, copier);        } else {            copier = BEAN_COPIERS.get(key);        }        copier.copy(srcObj, destObj, null);    }    /**     * 将转化的类的名字和被转化类型的名字作为key,保留到内存中     * @param srcClazz     * @param destClazz     * @return     */    private static String genKey(Class<?> srcClazz, Class<?> destClazz) {        return srcClazz.getName() + destClazz.getName();    }}
  log.info("+++++++++++BeanCopier放在缓存中+++++++++++++++");        //留神第一次是初始化BeanCopier,工夫会比拟长        BeanCopierWithCacheUtil beanCopierWithCacheUtil=new BeanCopierWithCacheUtil();        beanCopierWithCacheUtil.beanCopierWithCache();

这样耗时就会更短,转化的效率就更高了。
本篇文章由一文多发平台ArtiPub主动公布