1.Apache
BeanUtils 性能较差
PropertyUtils 不支持类型转换功能
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
UserDto dto = new UserDto();
//以下正常执行
BeanUtils.copyProperties(dto, oldUser);
//以下方法会抛出IllegalArgumentException异常
PropertyUtils.copyProperties(dto, oldUser);
2.Spring BeanUtils
User newUser = new User();
BeanUtils.copyProperties(oldUser, newUser);
3.Cglib BeanCopier 性能较好
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.0</version>
</dependency>
final BeanCopier copier = BeanCopier.create(User.class, UserDto.class, false);
UserDto dto = new UserDto();
copier.copy(oldUser, dto, null);
这里需要注意的是如果有字段类型不同需要手动开启并指定Converter,不然同名字段属性不同不会进行拷贝,如以上例子oldUser中的age(int类型)不会拷贝到dto中的age(Long类型),dto中的age改为Integer类型也不会拷贝。
4.mapstruct
MapStruct由于是在编译时生成相应的拷贝方法,因此性能很好,理论上拷贝速度是最快的。这里注意运行前需先进行 mvn compile 。
mapstruct默认是浅拷贝,如果需要深拷贝,需要在mapper上加注解 ``@Mapper(mappingControl = DeepClone.class)`
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.5.2.Final</version>
</dependency>
<!--注解处理器,根据注解自动生成mapper的实现-->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.2.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
<scope>provided</scope>
</dependency>
A.class
@NoArgsConstructor
@AllArgsConstructor
@Data
public class A {
private String name;
private String age;
private Long id;
private B b;
private List<B> bs;
}
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class ADto {
private String name;
private String age;
private String id;
private BDto b;
private List<BDto> bs;
}
@Mapper(componentModel = "spring")
public interface AMapper {
AMapper INSTANCE = Mappers.getMapper(AMapper.class);
// @Mapping(target = "name", ignore = true)
@Mapping(target = "id", expression = "java(String.valueOf(a.getId()))")
ADto po2Dto (A a);
List<ADto> po2Dto (List<A> as);
@Mapping(target = "id", expression = "java(getId(aDto.getId()))")
A dto2Po (ADto aDto);
List<A> po2Dtos (List<ADto> aDtos);
// @Mapping(target = "className", source = "className")
//@InheritInverseConfiguration(name = "getModelFromDto")
// ADto po2Dto(A a);
default Long getId(String id){
return Long.valueOf(id);
}
}
@NoArgsConstructor
@AllArgsConstructor
@Data
public class B {
private String name;
private String age;
private Long id;
}
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class BDto {
private String name;
private String age;
private String id;
}
@Mapper(componentModel = "spring")
public interface BMapper {
BMapper INSTANCE = Mappers.getMapper(BMapper.class);
@Mapping(target = "id", expression = "java(String.valueOf(b.getId()))")
BDto po2Dto (B b);
List<BDto> po2Dto (List<B> b);
@Mapping(target = "id", expression = "java(getId(bDto.getId()))")
B dto2Po (BDto bDto);
List<B> po2Dtos (List<BDto> bDtos);
// @Mapping(target = "className", source = "className")
//@InheritInverseConfiguration(name = "getModelFromDto")
// BDto po2Dto(B a);
default Long getId(String id){
return Long.valueOf(id);
}
}
@Test
public void test(){
BDto bDto = BDto.builder().id("33").age("29").name("jaja").build();
ArrayList<BDto> bDtos = new ArrayList<>();
bDtos.add(bDto);
bDtos.add(bDto);
bDtos.add(bDto);
bDtos.add(bDto);
bDtos.add(bDto);
ADto aDto = ADto.builder().id("1").age("28").name("sula").b(bDto).bs(bDtos).build();
long startTime = System.currentTimeMillis();
A a = AMapper.INSTANCE.dto2Po(aDto);
System.out.println("BeanUtils 100w次实体映射耗时:" + (System.currentTimeMillis() - startTime));
}