深入理解Java对象复制

网友投稿 250 2023-01-15

深入理解Java对象复制

一、图示

二、MapStruct

pom文件

junit

junit

4.12

org.projectlombok

lombok

1.18.16

commons-beanutils

commons-beanutils

1.9.4

org.mapstruct

mapstruct

1.2.0.Final

org.mapstruct

mapstruct-jdk8

1.2.0.Final

org.mapstruct

mapstruct-processor

1.2.0.Final

下载插件

插件的作用是为了在本地测试的时候,生成 接口的 impl 文件(生成的文件存在与target包里面)

如果是生产环境的话,和Lombok操作一样,需要在pom文件添加 mapStruct 插件依赖

org.apache.maven.plugins

maven-compiler-plugin&ltpiZHXhLSkd;/artifactId>

3.6.1

1.8

1.8

true

org.projectlombok

lombok

1.18.16

org.mapstruct

mapstruct-processor

1.2.0.Final

代码

import com.baomidou.mybatisplus.annotation.TableName;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

/**

* Created by yangLongFei on 2021/5/11 10:44

* Version: $

*/

@Data

@AllArgsConstructor

@NoArgsConstructor

@TableName

public class Student {

private Integer id;

private String name;

private String age;

private String phone;

private String address;

}

import lombok.Data;

import java.io.Serializable;

/**

* Created by yangLongFei on 2021/5/11 10:51

* Version: $

*/

@Data

public class StudentDTO implements Serializable {

private static final long serialVersionUID = 735190899850778343L;

private Integer id;

private String name;

private String age;

private String phone;

private String address;

}

import lombok.Data;

import java.io.Serializable;

/**

* Created by yangLongFei on 2021/5/11 16:59

* Version: $

*/

@Data

public class StudentVO implements Serializable {

private static final long serialVersionUID = 2059190505074790405L;

private Integer pk;

private String userName;

private String userAge;

private String userPhone;

private String userAddress;

}

接口

import com.sys.yang.dto.StudentDTO;

import com.sys.yang.entity.Student;

import com.sys.yang.vo.StudentVO;

import org.mapstruct.Mapper;

import org.mapstruct.Mapping;

import org.mapstruct.Mappings;

import org.mapstruct.factory.Mappers;

@Mapper

public interface ConverterStudent {

ConverterStudent INSTANCE = Mappers.getMapper(ConverterStudent.class);

@Mappings({

@Mapping(source = "name", target = "name"),

@Mapping(source = "age", target = "age")

})

StudentDTO entityToDTO(Student student);

@Mappings({

@Mapping(source = "id", target = "pk"),

@Mapping(source = "name", target = "userName"),

@Mapping(source = "age", target = "userAge"),

@Mapping(source = "phone", target = "userPhone"),

@Mapping(source = "address", target = "userAddress")

})

StudentVO dtoToVo(StudentDTO studentDTO);

}

测试类

import com.sys.yang.dto.StudentDTO;

import com.sys.yang.entity.Student;

import com.sys.yang.vo.StudentVO;

import org.junit.Test;

import org.springframework.beans.BeanUtils;

import java.lang.reflect.Method;

/**

* 对象转换,映射

* 方式1:效率最高 get set 方法

* 方式2:Common包 BeanUtils.copyProperties 反射的方式进行

* 方式3:mapstruct 推荐使用,操作不复杂,效率和 get set 方式相差不大

*

*

* Created by yangLongFei on 2021/5/11 10:43

* Version: $

*/

public class AToB {

/**

* set get 的时候使用

* 生成 对象的set方法

*/

public static void main(String[] args) {

Class clazz = StudentDTO.class;

Method[] fields = clazz.getDeclaredMethods();

for (Method field: fields) {

String name = field.getName();

if(!name.startsWith("is") && !name.startsWith("get")){

System.out.println("entity." + name + "()");

}

}

}

/**

* 测试方法

*/

@Test

public void test1() {

Student student = new Student(1,"zhagnsan","18","110112113114","diqiu");

System.out.println(student.toString());

StudentDTO studentDTO1 = new StudentDTO();

BeanUtils.copyProperties(student,studentDTO1);

System.out.println("BeanUtils: "+ studentDTO1.toString());

StudentDTO studentDTO2 = ConverterStudent.INSTANCE.entityToDTO(student);

System.out.println("mapstruct: entityToDTO " + studentDTO2.toString());

StudentVO studentVO = ConverterStudent.INSTANCE.dtoToVo(studentDTO2);

System.out.println("mapStruct: dtoToVo "+ studentVO);

}

}

生成的接口文件

三、framework cglib

要转换的对象的,字段名称 要和 原对象的字段名称一致,否则赋值会失败,可以手动 convert 方法,但是,实现后所有的转换内容都会走 convert 方法

代码

import lombok.Data;

import java.io.Serializable;

/**

* Created by yangLongFei on 2021/5/11 16:59

* Version: $

*/

@Data

public class StudentVO implements Serializable {

private static final long serialVersionUID = 2059190505074790405L;

private Integer pk;

private String userName;

private String userAge;

private String userPhone;

private String userAddress;

// framework cglib 使用到的内容

private String id;

private String name;

private Integer age;

private String phone;

private String address;

}

convert 实现类

import org.springframework.cglib.core.Converter;

/**

* Created by yangLongFei on 2021/5/11 19:53

* Version: $

*/

public class ConvertStudentDtoToVo implements Converter {

/**

* ⭐️⭐️⭐️⭐️⭐️ 要转换的属性名称,相同的情况下,才会走该方法

* @param o 原对象属性值,value

* @param aClass 目标对象属性 类型,class java.lang.String

* @param o1 目标对象属性set方法,setAddress

* @return

*/

@Override

public Object convert(Object o, Class aClass, Object o1) {

if (o.getClass().equals(aClass)) {

return o;

} else {

if (o instanceof Integer) {

return String.valueOf(o);

}

if (String.valueOf(o1).contains("Age")) {

return Integer.valueOf(o.toString());

}

return o;

}

}

}

测试方法

@Test

public void test2() {

Student student = new Student(1,"zhagnsan","18","110112113114","diqiu");

// false 表示不使用 转换器,

BeanCopier entityToDto = BeanCopier.create(Student.class, StudentDTO.class, false);

StudentDTO studentDTO3 = new StudentDTO();

// null 表示,不指定转换器,要使用转换器的化,需要实现 Converter 接口

// 属性名称之间不能指定映射关系,当属性名称不同的时候赋值操作会失败

entityToDto.copy(student, studentDTO3, null);

System.out.println("cglib :entityToDTO " + studentDTO3.toString());

BeanCopier dtoTOVo = BeanCopier.create(StudentDTO.class, StudentVO.class, false);

StudentVO studentVO1 = new StudentVO();

dtoTOVo.copy(studentDTO3, studentVO1, null);

System.out.println("cglib: dtoToVo " + studentVO1.toString());

// 一旦使用Converter,BeanCopier只使用Converter定义的规则去拷贝属性,所以在convert方法中要考虑所有的属性

http:// BeanCopier dtoTOVo2 = BeanCopier.create(StudentDTO.class, StudentVO.class, true);

StudentVO studentVO2 = new StudentVO();

dtoTOVo2.copy(studentDTO3, studentVO2, new ConvertStudentDtoToVo());

System.out.println("cglib : convert "+studentVO2.toString());

}

四、问题

beanUtils  不会进行 属性 类型的转换,如果字段名称相同,类型不同,不会对该字段进行赋值操作,( 测试方法中使用的 是 org.springframework.beans.BeanUtils )

cglib  在不定义Converter 的情况下也会出现 类型转换错误的异常,可以手动自定义转换器 convert ,一旦使用Converter,BeanCopier只使用Converter定义的规则去拷贝属性,所以在convert方法中要考虑所有的属性。

springframwork 有实现 cglib 的BeanCopier 不需要再引用 org.easymock 依赖

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:中通菜鸟物流查询(中通菜鸟快递官网)
下一篇:Java基础之SpringBoot整合knife4j
相关文章

 发表评论

暂时没有评论,来抢沙发吧~