深入理解Java对象复制

作者:yang_zzu 时间:2021-10-06 05:39:27 

一、图示

深入理解Java对象复制

二、MapStruct

pom文件


       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.12</version>
       </dependency>

<dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.18.16</version>
       </dependency>

<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
       <dependency>
           <groupId>commons-beanutils</groupId>
           <artifactId>commons-beanutils</artifactId>
           <version>1.9.4</version>
       </dependency>

<dependency>
           <groupId>org.mapstruct</groupId>
           <artifactId>mapstruct</artifactId>
           <version>1.2.0.Final</version>
       </dependency>
       <dependency>
           <groupId>org.mapstruct</groupId>
           <artifactId>mapstruct-jdk8</artifactId>
           <version>1.2.0.Final</version>
       </dependency>
       <dependency>
           <groupId>org.mapstruct</groupId>
           <artifactId>mapstruct-processor</artifactId>
           <version>1.2.0.Final</version>
       </dependency>

<!-- dozer使用时需要配置xml 文件,不推荐使用性能和 BeanUtils 差不多,使用过程可以参考 https://www.jianshu.com/p/bf8f0e8aee23-->
       <!-- https://mvnrepository.com/artifact/net.sf.dozer/dozer -->
       <!--<dependency>
           <groupId>net.sf.dozer</groupId>
           <artifactId>dozer</artifactId>
           <version>5.5.1</version>
       </dependency>-->

下载插件

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

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


<build>
       <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>3.6.1</version>
               <configuration>
                   <source>1.8</source>
                   <target>1.8</target>
                   <showWarnings>true</showWarnings>
                   <annotationProcessorPaths>
                       <path>
                           <groupId>org.projectlombok</groupId>
                           <artifactId>lombok</artifactId>
                           <version>1.18.16</version>
                       </path>
                       <path>
                           <groupId>org.mapstruct</groupId>
                           <artifactId>mapstruct-processor</artifactId>
                           <version>1.2.0.Final</version>
                       </path>
                   </annotationProcessorPaths>
               </configuration>
           </plugin>

</plugins>

</build>

深入理解Java对象复制

代码


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 方式相差不大
*
* <p>
* Created by yangLongFei on 2021/5/11 10:43
* Version: $
*/
public class AToB {

/**
    * set get 的时候使用
    * 生成 对象的set方法
    */
   public static void main(String[] args) {
       Class<StudentDTO> 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);

}

}

生成的接口文件

深入理解Java对象复制

三、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方法中要考虑所有的属性
       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 依赖

来源:https://blog.csdn.net/yang_zzu/article/details/116644050

标签:Java,对象,复制
0
投稿

猜你喜欢

  • java spring mvc处理器映射器介绍

    2021-11-22 01:01:35
  • java获取包下被指定注解的类过程解析

    2023-08-08 11:12:27
  • 如何在C# 中查找或结束程序域中的主、子进程

    2023-06-14 20:00:41
  • Java stream sorted使用 Comparator 进行多字段排序的方法

    2022-07-26 05:02:13
  • java 多线程死锁详解及简单实例

    2022-02-25 19:48:52
  • SpringMVC @RequestMapping注解详解

    2022-08-08 06:58:14
  • pom文件中${project.basedir}的使用

    2021-12-24 04:24:11
  • Sharding-Proxy基本功能用法介绍

    2021-10-17 06:41:03
  • JAVA WSIMPORT生成WEBSERVICE客户端401认证过程图解

    2023-11-14 00:27:55
  • Java lombok中@Accessors注解三个属性的作用

    2022-04-20 14:32:27
  • Eclipse自定义启动画面和图标的方法介绍

    2022-05-14 09:27:13
  • 聊聊Unity 自定义日志保存的问题

    2021-11-28 15:38:55
  • android的消息处理机制(图文+源码分析)—Looper/Handler/Message

    2023-01-04 08:04:15
  • 你真的知道Java中对象的销毁吗

    2022-09-14 22:31:38
  • 详解C#借助.NET框架中的XmlTextReader类读取XML的方法

    2023-01-18 23:31:47
  • Android实现掷骰子效果

    2022-06-16 01:09:16
  • java 文件下载支持中文名称的实例

    2023-03-16 09:02:16
  • 关于java 图形验证码的解决方法

    2023-08-09 15:21:19
  • C sharp (#) 数据类型获取方式

    2022-03-29 00:33:10
  • Android实现毛玻璃效果弹出菜单动画

    2023-04-22 17:02:12
  • asp之家 软件编程 m.aspxhome.com