2024年了,你还在使用BeanUtils进行对象的赋值吗?

前言

已经2024年了,你还在使用BeanUtils进行对象的赋值吗?如果你现在还在使用BeanUtils,看了本文,就会从此改用Mapstruct。

在我大学四年学习代码的过程中,在进行无数次DTO、VO和各种对象之间的值拷贝时一直在使用BeanUtils.copyProperties()这个方法,它也确实是一个好用的方法,简化了许多代码。在进行各种实体DTO对象的拷贝时只需要加一句BeanUtils.copyProperties()便能轻松赋值。但是在我开始实习进入工作之后发现了更为‘懒惰’的办法就可以完成对象之间的转换,那就是MapStruct

MapStruct简介

mapstruct是一种 实体类 映射框架,能够通过Java注解将一个实体类的属性安全地赋值给另一个实体类。有了mapstruct,只需要定义一个映射器接口,声明需要映射的方法,在编译过程中,mapstruct会自动生成该接口的实现类,实现将源对象映射到目标对象的效果。

mapstruct 相对于BeanUtils的优势在哪?
  • mapstruct支持复杂属性赋值,而BeanUtils很容易因为是浅拷贝导致一系列的问题。
  • mapstruct效率高,效率相当于自己手动get、set属性,而BeanUtils方法实现过程并不简单,是通过反射机制进行映射,相对于直接用get和set方法赋值,其性能开销更大。
  • mapstruct支持不同字段间的赋值,通过注解实现

实体类映射框架大致有两种:一种是运行期通过java反射机制动态映射;另一种是编译期动态生成getter/setter,在运行期直接调用框架编译好的class类实现实体映射。接下来我们看看各种实体类映射框架的效率对比。

效率对比:

image.png

从这张图表可以看到,MapStruct不仅好用,并且它的效率更是‘遥遥领先’。

MapStruct使用

MapStruct依赖

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-jdk8</artifactId>
    <version>${mapstruct.version}</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>${mapstruct.version}</version>
</dependency>

这边有几个要注意的点

  • mapstruct-jdk8和mapstruct-processor的版本号必须一致。
  • 如果你的项目中有用到了swagger框架的话,因为swagger里也有mapstruct,所以需要排除
   <groupId>io.springfox</groupId>
   <artifactId>springfox-swagger2</artifactId>
   <version>${swagger2.version}</version>
   <exclusions>
       <exclusion>
           <artifactId>mapstruct</artifactId>
           <groupId>org.mapstruct</groupId>
       </exclusion>
   </exclusions>

代码实现

实体类
@Data
@TableName("user")
public class User {

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    /**
     * 用户名
     */
    @TableField("name")
    private String name;
    
    /**
     * 邮箱
     */
    @TableField("mail")
    private String mail;

    /**
     * 0 男
     1 女
     2 未知
     */
    @TableField("sex")
    private Boolean sex;
}
DTO对象
@Data
public class UserDto {

    /**
     * 主键
     */
    private Integer id;

    /**
     * 用户名
     */
    private String name;

    /**
     * 邮箱
     */
    private String mail;

    /**
     * 0 男
     1 女
     2 未知
     */
    private Boolean sex;

}
Mapper接口
//mapstruct包下的mapper注解
@Mapper(componentModel = "spring")
public interface UserMapper {
    UserDto mapper(User user);
}

第一种使用情况

当两个对象的属性类型和名称完全相同时,Mapstruct会自动拷贝。

UserDto userDto = UserMapper.mapper(user);

只需要如上代码就可以完成对象的赋值。

第二种使用情况

当两个对象的属性类型和名称不完全相同时,可以用@Mapping注解进行绑定。 假设我们把userdto里的name改为了nickname,接下来只需要在mapper接口修改

//mapstruct包下的mapper注解
@Mapper(componentModel = "spring")
public interface UserMapper {
    @Mapping(target = "nickname", source = "name")
    UserDto mapper(User user);
}
拓展

当然我们还可以对这个mapper进行扩展实现自己更多的自定义功能,比如可以利用它完成集合转换数据源转换 等等,这些可以根据自己的需求进行拓展。

总结

从代码上我们可以看出MapStruct的使用的成本其实和BeanUtils差不多,但是MapStruct的高性能,可扩展性是远远优于BeanUtils的。在大型项目中往往存在着更多的性能和拓展性的问题,所以推荐大家学会MapStruct,告别BeanUtils。

  • 19
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值