javaBean 转换

一、前言
二、性能测试对比
三、12种转换案例

  1. get\set
  2. json2Json
  3. Apache copyProperties
  4. Spring copyProperties
  5. Bean Mapping
  6. Bean Mapping ASM
  7. BeanCopier
  8. Orika
  9. Dozer
  10. ModelMapper
  11. JMapper
  12. MapStruct
    四、总结

开始 :

用于对象属性转换有12种,
包括:普通的getset、json2Json、Apache属性拷贝、
Spring属性拷贝、bean-mapping、bean-mapping-asm、BeanCopier、
Orika、Dozer、ModelMapper、JMapper、MapStruct 

1. get\set

public Student getSet(StudentDto studentDto) {
    Student student = new Student();
    student.setName(studentDto.getName());
    student.setAge(studentDto.getAge());
    student.setHeight(studentDto.getHeight());
    return student;
}

1.1 注 : 性能高,需要手写
1.2. 其实这种方式也是日常使用的最多的,性能肯定是杠杠的,就是操作起来有点麻烦。尤其是一大堆属性的 VO
对象转换为 DTO 对象时候。但其实也有一些快捷的操作方式,比如你可以通过 Shift+Alt 选中所有属性,Shift+Tab
归并到一列,接下来在使用 Alt 选中这一列,批量操作粘贴 userDTO.set
以及快捷键大写属性首字母,最后切换到结尾补充括号和分号,最终格式化一下就搞定了。

2 . json2Json

 public Student getJson(StudentDto studentDto) {
        String s = JSON.toJSONString(studentDto);
        Student student = JSON.parseObject(s, Student.class);
        return student;
    }
    
把对象转JSON串,再把JSON转另外一个对象

3 . Apache copyProperties

 public Student getApacheCopyProperties(StudentDto studentDto) {
        Student student = new Student();
        try {
            BeanUtils.copyProperties(student,studentDto);
        } catch (BeansException e) {
            e.printStackTrace();
        }
        return student;
    }
Introspector 机制获取到类的属性来进行赋值操作
有坑,兼容性交差,不建议使用

4 Spring copyProperties

    public Student getSpringCopyProperties(StudentDto studentDto) {
        Student student = new Student();
        try {
            BeanUtils.copyProperties(studentDto, Student.class);
        } catch (BeansException e) {
            e.printStackTrace();
        }
        return student;
    }
Introspector机制获取到类的属性来进行赋值操作
样是反射的属性拷贝,Spring 提供的 copyProperties 要比 Apache 好用的多,
只要你不用错,基本不会有啥问题。

5 Bean Mapping

public Student getBeanMapping(StudentDto studentDto) {
    Student student = new Student();

    BeanUtil.copyProperties(studentDto, student;

    return student;
}
属性拷贝 
性能一般

6 Bean Mapping ASM

public Student getBeanMappingASM(StudentDto studentDto) {
    Student student = new Student();
    BeanUtil.copyProperties(studentDto, student);
    return student;
}
基于ASM字节码框架实现
与普通的 Bean Mapping 相比,性能有所提升,可以使用。

7 BeanCopier

  public Student getBeanCopier(StudentDto studentDto) {
        Student student = new Student();
        BeanCopier beanCopier = BeanCopier.create(studentDto.getClass(), student.getClass(), false);
        beanCopier.copy(studentDto,studentDto,null);
        return student;
    }
基于CGlib字节码操作生成get、set方法
整体性能很不错,使用也不复杂,可以使用

8 Orika

 * 构造一个MapperFactory
 */
private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

static {
    mapperFactory.classMap(UserDTO.class, UserVO.class)
            .field("userId", "userId")  // 字段不一致时可以指定
            .byDefault()
            .register();
}

@Override
public UserDTO sourceToTarget(UserVO var) {
    return mapperFactory.getMapperFacade().map(var, UserDTO.class);
}

}
基于字节码生成映射对象在这里插入代码片
测试性能不是太突出,如果使用的话需要把 MapperFactory 的构建优化成 Bean 对象

9 Dozer

private static DozerBeanMapper mapper = new DozerBeanMapper();
@Override
public UserDTO sourceToTarget(UserVO var) {
    return mapper.map(var, UserDTO.class);
}

官网 :
http://dozer.sourceforge.net/documentation/gettingstarted.html

属性映射框架,递归的方式复制对象
性能有点差,不建议使用

10. ModelMapper

 private static ModelMapper modelMapper = new ModelMapper();

        static {
            modelMapper.addMappings(new PropertyMap() {
                @Override
                protected void configure() {
                    // 属性值不一样可以自己操作
                    map().setUserId(source.getUserId());
                }
            });
        }

        @Override
        public UserDTO sourceToTarget (UserVO var){
            return modelMapper.map(var, UserDTO.class);
        }
    }

官网:
http://modelmapper.org

基于ASM字节码实现
转换对象数量较少时性能不错,如果同时大批量转换对象,性能有所下降

11. JMapper

JMapper jMapper = new JMapper<>(UserDTO.class, UserVO.class, new JMapperAPI()
        .add(JMapperAPI.mappedClass(UserDTO.class)
                .add(JMapperAPI.attribute("userId")
                        .value("userId"))
                .add(JMapperAPI.attribute("userNickName")
                        .value("userNickName"))
                .add(JMapperAPI.attribute("createTime")
                        .value("createTime"))
        ));

官网:
https://github.com/jmapper-framework/jmapper-core/wiki

Elegance, high performance and robustness all in one java bean mapper
速度真心可以,不过结合 SpringBoot 感觉有的一点点麻烦,可能姿势不对

12 MapStruct

@Mapper(componentModel = “spring”, unmappedTargetPolicy = ReportingPolicy.IGNORE, unmappedSourcePolicy = ReportingPolicy.IGNORE)
public interface UserDTOMapping extends IMapping {

/** 用于测试的单例 */
IMapping INSTANCE = Mappers.getMapper(UserDTOMapping.class);

@Mapping(target = "userId", source = "userId")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
@Override
UserDTO sourceToTarget(UserVO var1);

@Mapping(target = "userId", source = "userId")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
@Override
UserVO targetToSource(UserDTO var1);

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

手段:直接在编译期生成对应的get、set,像手写的代码一样
点评:速度很快,不需要到运行期处理,结合到框架中使用方便

你可能感兴趣的:(java)