• 高性能Java对象转换工具MapStruct


    ​欢迎光临我的博客查看最新文章: https://river106.cn

    Java日常开发中经常涉及到各种对象的转换,如:VO、DO、DTO等,我们经常会借助工具来转换对象以减轻工作量、提升工作效率,如Apache的BeanUtils,Spring的BeanUtils、Cglib的BeanCopier、阿里的FastJson等,
    本篇介绍另一个高性能的对象转换工具:MapStruct

    1、MapStruct简介

    MapStruct是一个生成类型安全、高性能且无依赖的JavaBean映射代码的注解处理器。

    官网: https://mapstruct.org/
    github: https://github.com/mapstruct/mapstruct

    2、MapStruct使用

    2.1、引入依赖

    
        org.mapstruct
        mapstruct
        1.4.2.Final
    
    
        org.mapstruct
        mapstruct-processor
        1.4.2.Final
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    lombok一起使用的话,需要注意lombok的版本,否则可能出现问题, 如编译后的实现类未进行get set处理。

    
        org.projectlombok
        lombok
        1.18.8
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用Idea的话,开启注解处理:
    File->Settings->Build,Execulion,Development->Complier->Annotation Processors
    勾选Enable annotation processing

    2.2、定义需要转换的类

    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    public class Person {
        private Long id;
        private String name;
        private Integer age;
        private String email;
        private Date birthday;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    @ToString
    public class PersonDTO {
        private Long id;
        private String name;
        private Integer age;
        private String email;
        /**
         * 与 Person 的 birthDay 不一致
         */
        private Date birth;
        /**
         * 对 Person 的birthDay进行拓展, dateFormat的形式
         */
        private String birthDateFormat;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.3、定义映射类

    @Mapper
    public interface PersonMapper {
    
        PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
    
        @Mappings({
                @Mapping(source = "birthday", target = "birth"),
                @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
                @Mapping(target = "email", ignore = true)
        })
        PersonDTO convert(Person person);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    @Mapper 只有在接口加上这个注解, MapStruct才会去实现该接口
    @Mapper 里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个:
    default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象
    spring:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
    @Mapping:属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性
    source:源属性
    target:目标属性
    dateFormat:String到Date日期之间相互转换,通过SimpleDateFormat进行日期格式化
    ignore: 忽略这个字段
    @Mappings:配置多个@Mapping

    代码编译后,我们可以在target下看到自动生成的实现类PersonMapperImpl:

    public class PersonMapperImpl implements PersonMapper {
    
        @Override
        public PersonDTO convert(Person person) {
            if ( person == null ) {
                return null;
            }
    
            PersonDTO personDTO = new PersonDTO();
    
            personDTO.setBirth( person.getBirthday() );
            if ( person.getBirthday() != null ) {
                personDTO.setBirthDateFormat( new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format( person.getBirthday() ) );
            }
            personDTO.setId( person.getId() );
            personDTO.setName( person.getName() );
    
            return personDTO;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.4、测试

    public class PersonConverterTest {
    
        public static void main(String[] args) {
            Person person = new Person(1L, "river106", "xxx@gmail.com", new Date());
            PersonDTO personDTO = PersonMapper.INSTANCE.convert(person);
            System.out.println(personDTO);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.5、交由Spring管理

    添加spring相关依赖:

     
        org.springframework
        spring-context
        5.1.5.RELEASE
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    新增转换类PersonMapperSpring,@Mapper注解componentModel属性改为spring;

    @Mapper(componentModel = "spring")
    public interface PersonMapperSpring {
    
        @Mappings({
                @Mapping(source = "birthday", target = "birth"),
                @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
                @Mapping(target = "email", ignore = true)
        })
        PersonDTO convert(Person person);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试:

    @Configuration
    @ComponentScan(value = "cn.river.mapstruct")
    public class PersonConverterSpringTest {
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context =
                    new AnnotationConfigApplicationContext(PersonConverterSpringTest.class);
            Person person = new Person(1L, "river106", "xxx@gmail.com", new Date());
            PersonMapperSpring bean = context.getBean(PersonMapperSpring.class);
            PersonDTO personDTO = bean.convert(person);
            System.out.println(personDTO);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3、和其他转换工具性能对比

    使用如上简单对象,转换1000000次结果如下(时间单位:毫秒):

    fastjson :2862
    springBeanUtils :495
    beanCopier :122
    mapstruct :16

    从测试结果来看,MapStruct转换性能是最好的。

  • 相关阅读:
    【浅学Java】排序大全
    SAP PP学习笔记23 - 生产订单(制造指图)的元素2 - 决济规则(结算规则)
    华为机试:连续出牌数量
    配置Super-VLAN下的DHCP服务器示例
    SOLID,面向对象设计五大基本原则
    怎样处理专利申请优先权呢?
    树结构导学
    JavaWeb—HTTP状态 405 - 方法不允许【BUG已解决】
    图扑软件荣获第七届“创客中国”中小企业创新创业大赛优胜奖!
    在有序数组中插入一个数
  • 原文地址:https://blog.csdn.net/angellee1988/article/details/127833547