【业务功能篇71】Cglib的BeanCopier进行Bean对象拷贝

选择Cglib的BeanCopier进行Bean拷贝的理由是,
其性能要比Spring的BeanUtils,Apache的BeanUtils和PropertyUtils要好很多,
尤其是数据量比较大的情况下。

  • BeanCopier的主要作用是将数据库层面的Entity转化成service层的POJO。BeanCopier其实已经有很多开源版本,例如DozerMapper、Apache BeanUtils、Spring、Jodd BeanUtils甚至是Cglib都提供了这样的功能。我们这里讲的BeanCopier来自net.sf.cglib.BeanCopier包,cglib是一款比较底层的操作java字节码的框架。 而其他多数都是基于 反射 来实现的 对象复制,所以更底层的字节码方式获取数据赋值,效率会更高
  • 顾名思义,BeanCopier是用于在两个bean之间进行属性拷贝的。BeanCopier支持两种方式,一种是不使用Converter的方式,仅对两个bean间属性名和类型完全相同的变量进行拷贝。另一种则引入Converter,可以对某些特定属性值进行特殊操作。

简单用例 


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;
 
import java.math.BigDecimal;
 
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
 
import static org.junit.jupiter.api.Assertions.*;
 
class BeanCopyUtilsTest {
 
    /**
     * 测试说明: 类型不同BeanCopier不会拷贝
     */
    @Test
    void copy() {
        User user = new User();
        user.setId(1);
        user.setName("dearth");
        BeanCopier copier = BeanCopier.create(User.class, UserVo.class, false);
        UserVo userVo = new UserVo();
        copier.copy(user, userVo, null);
        Assertions.assertNull(userVo.getId());
    }
 
    /**
     * 测试说明: 提供转换器可以实现不同类型的拷贝
     */
    @Test
    void copyUseConverter() {
        User user = new User();
        user.setId(1);
        user.setName("dearth");
        user.setCreateTime(new Timestamp(10043143243L));
        user.setBalance(BigDecimal.valueOf(4000L));
        BeanCopier copier = BeanCopier.create(User.class, UserVo.class, true);
        UserVo vo = new UserVo();
        copier.copy(user, vo, new UserConverter());
        Assertions.assertNotNull(vo.getCreateTime());
        Assertions.assertNotNull(vo.getBalance());
    }
 
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static
    class User {
        private String name;
        private int id;
        private Timestamp createTime;
        private BigDecimal balance;
    }
 
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static
    class UserVo {
        private String name;
        private Integer id;
        private String createTime;
        private String balance;
    }
 
    static class UserConverter implements Converter {
 
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
        @Override
        public Object convert(Object o, Class aClass, Object o1) {
            if (o instanceof Integer) {
                return (Integer) o;
            } else if (o instanceof Timestamp) {
                Timestamp data = (Timestamp) o;
                return sdf.format(data);
            } else if (o instanceof BigDecimal) {
                BigDecimal bg = (BigDecimal) o;
                return bg.toPlainString();
            } else {
                 return null;
            }
        }
    }
}

 

  1. BeanCopier只拷贝名称和类型都相同的属性。
  2. 当目标类的setter数目比getter少时,创建BeanCopier会失败而导致拷贝不成功。
  3. 自定义Converter转换器可以转换不同类型的属性

 

你可能感兴趣的:(业务场景实例问题,Java,Spring,boot,java,spring,boot,对象拷贝)