BeanCopier copy

发布时间 2023-06-09 17:43:14作者: 懒阳阳是小学生

参考:  BeanCopier  copy

使用:

org.springframework.cglib.beans.BeanCopier


BeanCopier是用于在两个bean之间进行属性拷贝的。BeanCopier支持两种方式:

1、一种是不使用Converter的方式,仅对两个bean间属性名和类型完全相同的变量进行拷贝;
2、另一种则引入Converter,可以对某些特定属性值进行特殊操作。

Teacher类

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    Integer id;
    public String name;
    private Integer gender;
}

UserDO类
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.util.Date;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDO {

    private Integer id;
    protected String name;
    // 余额
    BigDecimal balance;
    Teacher teacher;
    public String pwd;
    public Date createTime;

}

UserDTO类
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {

    // 类中定义,必须为包装类型,这里只是为了演示效果
    private int id;
    protected String name;
    // 余额
    String balance;
    Teacher teacher;
    public String otherMember;
    public String createTime;

}

 

 

测试类

import org.junit.Test;
import org.springframework.cglib.beans.BeanCopier;

import java.math.BigDecimal;
import java.util.Date;

public class SpringBeanCopierTest {

    @Test
    public void test01() {
        UserDO userDO = this.getUserDO();
        System.out.println(userDO);
//        UserDO(id=1, name=zhangsan, balance=10.24, teacher=Teacher(id=1, name=teacher1, gender=1), pwd=111111, createTime=Fri Jun 09 16:57:59 CST 2023)
        // false不使用转换器
        BeanCopier copier = BeanCopier.create(UserDO.class, UserDTO.class, false);
        UserDTO userDTO = new UserDTO();
        copier.copy(userDO, userDTO, null);
        System.out.println(userDTO);
//        UserDTO(id=0, name=zhangsan, balance=null, teacher=Teacher(id=1, name=teacher1, gender=1), otherMember=null, createTime=null)

        userDO.getTeacher().setName("teacher2");

        // BeanCopier也存在浅拷贝问题
        System.out.println(userDO);
        System.out.println(userDTO);
//        UserDO(id=1, name=zhangsan, balance=10.24, teacher=Teacher(id=1, name=teacher2, gender=1), pwd=111111, createTime=Fri Jun 09 16:57:59 CST 2023)
//        UserDTO(id=0, name=zhangsan, balance=null, teacher=Teacher(id=1, name=teacher2, gender=1), otherMember=null, createTime=null)
    }

    @Test
    public void test02() {
        UserDO userDO = this.getUserDO();
        System.out.println(userDO);
//        UserDO(id=1, name=zhangsan, balance=10.24, teacher=Teacher(id=1, name=teacher1, gender=1), pwd=111111, createTime=Fri Jun 09 16:58:47 CST 2023)
        // true使用转换器
        BeanCopier copier = BeanCopier.create(UserDO.class, UserDTO.class, true);
        UserDTO userDTO = new UserDTO();
        copier.copy(userDO, userDTO, new UserDOToDTOConverter());
        System.out.println(userDTO);
//        UserDTO(id=1, name=zhangsan, balance=10.24, teacher=Teacher(id=1, name=teacher1, gender=1), otherMember=null, createTime=2023-06-09 16:58:47)

        userDO.getTeacher().setName("teacher2");

        // BeanCopier也存在浅拷贝问题
        System.out.println(userDO);
        System.out.println(userDTO);
//        UserDO(id=1, name=zhangsan, balance=10.24, teacher=Teacher(id=1, name=teacher2, gender=1), pwd=111111, createTime=Fri Jun 09 16:58:47 CST 2023)
//        UserDTO(id=1, name=zhangsan, balance=10.24, teacher=Teacher(id=1, name=teacher2, gender=1), otherMember=null, createTime=2023-06-09 16:58:47)
    }

    private UserDO getUserDO() {
        Teacher teacher = Teacher.builder().id(1).name("teacher1").gender(1).build();
        BigDecimal balance = BigDecimal.valueOf(10.24);
        UserDO userDO = UserDO.builder().id(1).name("zhangsan").balance(balance).teacher(teacher).pwd("111111").createTime(new Date()).build();
        return userDO;
    }
}

 

 

 

一  test01()不使用Converter

通过结果发现:UserDO的int类型的属性, 无法拷贝到UserDTO的Integer。.

即:BeanCopier 只拷贝名称和类型都相同的属性。

即使源类型是原始类型(int, short和char等),目标类型是其包装类型(Integer, Short和Character等),或反之:都不会被拷贝。

二 test02()使用Converter

1、一旦使用Converter,BeanCopier只使用Converter定义的规则去拷贝属性,所以在convert()方法中要考虑所有的属性;
2、毫无疑问,使用Converter会使对象拷贝速度变慢。

 

三 总结

当源类和目标类的属性名称、类型都相同,拷贝没问题。
当源对象和目标对象的属性名称相同、类型不同,那么名称相同而类型不同的属性不会被拷贝。注意,原始类型(int,short,char)和 他们的包装类型,在这里都被当成了不同类型,因此不会被拷贝。
源类或目标类的setter比getter少,拷贝没问题,此时setter多余,但是不会报错。
源类和目标类有相同的属性(两者的getter都存在),但是目标类的setter不存在,此时会抛出NullPointerException。
加缓存可以提升拷贝速度。