小程序网站google下载官方版
选择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不会拷贝*/@Testvoid 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());}/*** 测试说明: 提供转换器可以实现不同类型的拷贝*/@Testvoid 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@AllArgsConstructorstaticclass User {private String name;private int id;private Timestamp createTime;private BigDecimal balance;}@Data@NoArgsConstructor@AllArgsConstructorstaticclass 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");@Overridepublic 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;}}}
}
- BeanCopier只拷贝名称和类型都相同的属性。
- 当目标类的setter数目比getter少时,创建BeanCopier会失败而导致拷贝不成功。
- 自定义Converter转换器可以转换不同类型的属性