⚠️ This article is the first contract article in the nuggets community. It is prohibited to reprint without authorization

Blog: bugstack.cn

Precipitation, share, grow, let yourself and others can gain something! 😄

One, foreword

Why is your code just working?

How do you write code with no technical depth, no knowledge, and no experience? Baidu ah, encounter a problem this search a bit, that check a piece, no matter what principle it is or suitable for what kind of scene, first paste to their own project, look, can run, can run. Such code is only deliverable to the extent that it can be used, there is no guarantee of quality at all, let alone data structure, algorithm logic and design pattern, that depends on the programming data brush LeetCode, all rest.

When you feel read a lot of information and won’t use, what will say, true volume, have learned so. But in fact, I do not feel the deep digging of technology, combing a complete set of knowledge system, a little bit of cultivation a little bit of harvest is in volume. On the contrary, it is as easy to watch technical videos as watching movies. If you do not write cases, you will think that the book will be cool. The lack of mental thinking and mechanical physical repetition are meaningless.

Like if you use a property copy tool to convert VO to DTO, which one do you use, Apache or Spring, or something else, which is the most efficient? Next, we will use the data to verify, and provide a comparison of the use of various cases

Second, performance test comparison

In the process of Java system engineering development, there will be object conversion between various layers, such as VO, DTO, PO, VO, etc., and if all manual GET and set is too time-consuming, and may also be wrong operation, so it will be more convenient to choose an automatic tool.

At present, I have sorted out 12 kinds of object property conversion, including: General getSet, json2Json, Apache property copy, Spring property copy, bean-Mapping, bean-Mapping-ASM, BeanCopier, Orika, Dozer, ModelMapper, JMapper, MapSt Ruct Next, we tested the performance time comparison of these 11 attribute conversion operations at 100 times, 1,000 times, 10,000 times, 100,000 times and one million times respectively.

  • BeanUtils.copyPropertiesIs the most common utility class in your code, as long as you don’t use it incorrectlyApachePackage, but using Spring, and there is basically no performance impact.
  • But if the performance is better, you can replace manualThe get and set, orMapStructBetter because it is itself generated at compile timeThe get and setCode, and we writeThe get and setThe same.
  • Some other component packages are primarily based onAOP,ASM,CGlib, the technical means to achieve, so there will be corresponding performance loss.

Three, 12 conversion cases

Source: github.com/fuzhengwei/…

Description: Interfaces. assembler#sourceToTarget(SOURCE var) The learning process can be directly downloaded to run debugging.
,>

1. get\set

@Component
public class GetSetAssembler implements IAssembler<UserVO.UserDTO> {

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        UserDTO userDTO = new UserDTO();
        userDTO.setUserId(var.getUserId());
        userDTO.setUserNickName(var.getUserNickName());
        userDTO.setCreateTime(var.getCreateTime());
        returnuserDTO; }}Copy the code
  • Recommendation: u u u do do
  • Performance: u u u u u
  • Method: Handwriting
  • review: In fact, this way is also the daily use of the most, performance must be heavy, is a little trouble to operate. Especially when VO objects with a bunch of attributes are converted to DTO objects. For example, you can use Shift+Alt to select all attributes, Shift+Tab to merge into a column, and then use Alt to select that column and paste it in batchesuserDTO.setAnd the shortcut to uppercase, and then finally to the end to add parentheses and semicolons, and then finally to format it.

2. json2Json

@Component
public class Json2JsonAssembler implements IAssembler<UserVO.UserDTO> {

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        String strJson = JSON.toJSONString(var);
        returnJSON.parseObject(strJson, UserDTO.class); }}Copy the code
  • Recommendation: being fostered fostered fostered fostered
  • Performance: u being fostered fostered fostered
  • Method: Convert an object to a JSON string, and then convert JSON to another object
  • Comment on: so write mostly a little burn!

3. Apache copyProperties

@Component
public class ApacheCopyPropertiesAssembler implements IAssembler<UserVO.UserDTO> {

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        UserDTO userDTO = new UserDTO();
        try {
            BeanUtils.copyProperties(userDTO, var);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        returnuserDTO; }}Copy the code
  • Recommendation: being fostered fostered fostered fostered
  • Performance: u being fostered fostered fostered
  • Method: The Introspector mechanism obtains class attributes for assigning values
  • Comments: pit, poor compatibility, not recommended

4. Spring copyProperties

@Component
public class SpringCopyPropertiesAssembler implements IAssembler<UserVO.UserDTO> {

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(var, userDTO);
        returnuserDTO; }}Copy the code
  • Recommendation: u u u do do
  • Performance: u u u u do
  • Method: The Introspector mechanism obtains class attributes for assigning values
  • Comments: The same is the reflection of the property copy, Spring provides a much better use of copyProperties than Apache, as long as you are not wrong, basically no problem.

5. Bean Mapping

@Component
public class BeanMappingAssembler implements IAssembler<UserVO.UserDTO> {

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        UserDTO userDTO = new UserDTO();
        BeanUtil.copyProperties(var, userDTO);
        returnuserDTO; }}Copy the code
  • Recommendation: painted painted fostered fostered fostered
  • Performance: u u u do do
  • Method: Property copy
  • Comments: General performance

6. Bean Mapping ASM

@Component
public class BeanMappingAssembler implements IAssembler<UserVO.UserDTO> {

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        UserDTO userDTO = new UserDTO();
        BeanUtil.copyProperties(var, userDTO);
        returnuserDTO; }}Copy the code
  • Recommendation: u u u do do
  • Performance: u u u u do
  • Means: based on ASM bytecode framework
  • Comments: Compared with ordinary Bean Mapping, the performance is improved and can be used.

7. BeanCopier

@Component
public class BeanCopierAssembler implements IAssembler<UserVO.UserDTO> {

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        UserDTO userDTO = new UserDTO();
        BeanCopier beanCopier = BeanCopier.create(var.getClass(), userDTO.getClass(), false);
        beanCopier.copy(var, userDTO, null);
        returnuserDTO; }}Copy the code
  • Recommendation: u u u do do
  • Performance: u u u u do
  • Method: Generate get and SET methods based on CGlib bytecode operation
  • Comments: the overall performance is very good, use is not complex, can be used

8. Orika

@Component
public class OrikaAssembler implements IAssembler<UserVO.UserDTO> {

    /** * construct a MapperFactory */
    private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    static {
        mapperFactory.classMap(UserDTO.class, UserVO.class)
                .field("userId"."userId")  // Can be specified if the field is inconsistent
                .byDefault()
                .register();
    }

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        return mapperFactory.getMapperFacade().map(var, UserDTO.class); }}Copy the code
  • Website: orika – mapper. Making. IO/orika – docs /
  • Recommendation: painted painted fostered fostered fostered
  • Performance: u u u do do
  • Means: generate mapping objects based on bytecode
  • Comments: The test performance is not too outstanding, if used need to optimize MapperFactory build into Bean objects

9. Dozer

@Component
public class DozerAssembler implements IAssembler<UserVO.UserDTO> {

    private static DozerBeanMapper mapper = new DozerBeanMapper();

    @Override
    public UserDTO sourceToTarget(UserVO var) {
        return mapper.map(var, UserDTO.class); }}Copy the code
  • Liverpoolfc.tv: dozer.sourceforge.net/documentati…
  • Recommendation: u fostered fostered fostered fostered
  • Performance: painted painted fostered fostered fostered
  • Means: attribute mapping framework, recursive way to copy objects
  • Comments: performance is a little poor, not recommended

10. ModelMapper

@Component
public class ModelMapperAssembler implements IAssembler<UserVO.UserDTO> {

    private static ModelMapper modelMapper = new ModelMapper();

    static {
        modelMapper.addMappings(new PropertyMap<UserVO, UserDTO>() {
            @Override
            protected void configure(a) {
                // If the value of the attribute is different, it can be operated by itselfmap().setUserId(source.getUserId()); }}); }@Override
    public UserDTO sourceToTarget(UserVO var) {
        return modelMapper.map(var, UserDTO.class); }}Copy the code
  • Website: modelmapper.org
  • Recommendation: u u u do do
  • Performance: u u u do do
  • Means: based on ASM bytecode implementation
  • Comments: If the number of converted objects is small, the performance is good. If the number of converted objects is large, the performance is reduced

11. JMapper

JMapper<UserDTO, UserVO> 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"))));Copy the code
  • Liverpoolfc.tv: github.com/jmapper-fra…
  • Recommendation: u u u u do
  • Performance: u u u u u
  • Elegance, high performance, and robustness all in one Java bean mapper
  • Comments: speed really can, but combined with SpringBoot feel a little trouble, may be wrong posture

12. MapStruct

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, unmappedSourcePolicy = ReportingPolicy.IGNORE)
public interface UserDTOMapping extends IMapping<UserVO.UserDTO> {

    /** A singleton for testing */
    IMapping<UserVO, UserDTO> 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);

}
Copy the code
  • Liverpoolfc.tv: github.com/mapstruct/m…
  • Recommendation: u u u u u
  • Performance: u u u u u
  • Method: Generate the corresponding GET and set directly at compile time, like handwritten code
  • Comments: fast, do not need to run time processing, combined with the framework of easy to use

Four,

  • In fact, the operation of object attribute conversion is nothing more than reflection, AOP, CGlib, ASM, Javassist at compile time and run time processing, there is a good idea is to generate the corresponding GET, set before compilation, just like handwritten.
  • So I prefer my favorite MapStruct, which is more comfortable to use, one is from the function of expansion, ease of use and compatibility.
  • Either way, do complete testing and validation. Don’t just copy and paste, or you might end up with a hole in the ground.