使用MapStruct替换BeanUtils的一次优化

背景

最初是组长提出了让我用性能更高的mapstruct

如果你现在还在使用BeanUtils,看了本文,也会像我一样,从此改用Mapstruct。

对象之间的属性拷贝,之前用的是Spring的BeanUtils,有一次,在学习领域驱动设计的时候,看了一位大佬的文章,他在文章中提到使用Mapstruct做DO和Entity的相互转换,出于好奇,后来就去了解了一下Mapstruct,发现这个工具确实优秀,所以果断弃用BeanUtils。

Mapstruct 性能优于 BeanUtils 的原因

Java程序执行的过程,是由编译器先把java文件编译成class字节码文件,然后由JVM去解释执行class文件。Mapstruct正是在java文件到class这一步帮我们实现了转换方法,即做了预处理,提前编译好文件。

修改前的代码

 @Override
    public void add(Recorder recorder) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        Score score = new Score();
        score.setTaskId(recorder.getTaskId());
        LoginUser loginUser = (LoginUser) StpUtil.getSession().get("user");
        score.setUserId(loginUser.getId());
        TaskMetricsCofiguration t = taskMetricsMapper.getTaskMetricsConfigurationByTaskId(recorder.getTaskId());
        TaskMetricsCofigurationAndRecorderDto dto = new TaskMetricsCofigurationAndRecorderDto();
        //使用BeanUtils进行属性复制将参数合并到TaskMetricsCofigurationAndRecorderDto
        BeanUtils.copyProperties(t, dto);
        BeanUtils.copyProperties(recorder, dto);

        // 使用BeanUtils进行属性复制将参数放到RecorderDto
        BeanUtils.copyProperties(recorder, score);

        //通过反射注入参数到score
        RemarkScoreEx item1 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem1, dto.getLefthandInstrumentTotaltimeRecorder()));
        processRemarkScore(item1, score, RuleItem1);
        RemarkScoreEx item2 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem2, dto.getRighthandInstrumentTotaltimeRecorder()));
        processRemarkScore(item2, score, RuleItem2);
        RemarkScoreEx item3 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem3, dto.getLefthandInstrumentPathLengthRecorder()));
        processRemarkScore(item3, score, RuleItem3);
        RemarkScoreEx item4 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem4, dto.getRighthandInstrumentPathLengthRecorder()));
        processRemarkScore(item4, score, RuleItem4);

        RemarkScoreEx item5 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem5, dto.getLefthandInstrumentAnglepathRecorder()));
        processRemarkScore(item5, score, RuleItem5);
        RemarkScoreEx item6 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem6, dto.getRighthandInstrumentAnglepathRecorder()));
        processRemarkScore(item6, score, RuleItem6);
        RemarkScoreEx item7 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem7, dto.getLefthandLostTargetViolationsTotalnumRecorder()));
        processRemarkScore(item7, score, RuleItem7);
        RemarkScoreEx item8 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem8, dto.getRighthandLostTargetViolationsTotalnumRecorder()));
        processRemarkScore(item8, score, RuleItem8);

        RemarkScoreEx item9 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem9, dto.getDeviceOffScreenViolationsTotalnumRecorder()));
        processRemarkScore(item9, score, RuleItem9);
        RemarkScoreEx item10 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem10, dto.getDeviceOffScreenViolationsTotaltimeRecorder()));
        processRemarkScore(item10, score, RuleItem10);
        RemarkScoreEx item11 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem11, dto.getAccidentalCollisionDamageViolationsTotalnumRecorder()));
        processRemarkScore(item11, score, RuleItem11);
        RemarkScoreEx item12 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem12, dto.getMaximumDamageDepthRecorder()));
        processRemarkScore(item12, score, RuleItem12);
        RemarkScoreEx item13 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem13, dto.getTaskUsetimeRecorder()));
        processRemarkScore(item13, score, RuleItem13);
        score.setUserId(loginUser.getId());
        score.setScoreId(scoreMapper.selectMaxId() + 1);
        scoreMapper.insert(score);
    }

修改后的代码

这里解决了两个问题,第一个是两个对象合成一个dto对象,而且其中这两个对象包含了相同的字段需要处理
@Mapping(source = “recorder.taskId”, target = “taskId”)

    public void add(Recorder recorder) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        LoginUser loginUser = (LoginUser) StpUtil.getSession().get("user");
        TaskMetricsCofiguration t = taskMetricsMapper.getTaskMetricsConfigurationByTaskId(recorder.getTaskId());
        TaskMetricsCofigurationAndRecorderDto dto = com.wego.training.mapstruct.TaskMetricsMapper.INSTANCE.toTaskMetricsDto(t, recorder);

        // 使用BeanUtils进行属性复制将参数放到RecorderDto
        // 使用RecorderMapper进行映射
        RecorderMapper recorderMapper = Mappers.getMapper(RecorderMapper.class);
        Score score = recorderMapper.toScore(recorder);
        score.setTaskId(recorder.getTaskId());
        score.setUserId(loginUser.getId());

        //通过反射注入参数到score
        RemarkScoreEx item1 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem1, dto.getLefthandInstrumentTotaltimeRecorder()));
        processRemarkScore(item1, score, RuleItem1);
        RemarkScoreEx item2 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem2, dto.getRighthandInstrumentTotaltimeRecorder()));
        processRemarkScore(item2, score, RuleItem2);
        RemarkScoreEx item3 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem3, dto.getLefthandInstrumentPathLengthRecorder()));
        processRemarkScore(item3, score, RuleItem3);
        RemarkScoreEx item4 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem4, dto.getRighthandInstrumentPathLengthRecorder()));
        processRemarkScore(item4, score, RuleItem4);

        RemarkScoreEx item5 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem5, dto.getLefthandInstrumentAnglepathRecorder()));
        processRemarkScore(item5, score, RuleItem5);
        RemarkScoreEx item6 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem6, dto.getRighthandInstrumentAnglepathRecorder()));
        processRemarkScore(item6, score, RuleItem6);
        RemarkScoreEx item7 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem7, dto.getLefthandLostTargetViolationsTotalnumRecorder()));
        processRemarkScore(item7, score, RuleItem7);
        RemarkScoreEx item8 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem8, dto.getRighthandLostTargetViolationsTotalnumRecorder()));
        processRemarkScore(item8, score, RuleItem8);

        RemarkScoreEx item9 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem9, dto.getDeviceOffScreenViolationsTotalnumRecorder()));
        processRemarkScore(item9, score, RuleItem9);
        RemarkScoreEx item10 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem10, dto.getDeviceOffScreenViolationsTotaltimeRecorder()));
        processRemarkScore(item10, score, RuleItem10);
        RemarkScoreEx item11 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem11, dto.getAccidentalCollisionDamageViolationsTotalnumRecorder()));
        processRemarkScore(item11, score, RuleItem11);
        RemarkScoreEx item12 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem12, dto.getMaximumDamageDepthRecorder()));
        processRemarkScore(item12, score, RuleItem12);
        RemarkScoreEx item13 = RecorderUtil.setScoreEachItemByScoringRules(createRemarkScoreByValue(dto, RuleItem13, dto.getTaskUsetimeRecorder()));
        processRemarkScore(item13, score, RuleItem13);
        score.setUserId(loginUser.getId());
        score.setScoreId(scoreMapper.selectMaxId() + 1);
        scoreMapper.insert(score);
    }

package com.wego.training.mapstruct;

import com.wego.training.domain.Recorder;
import com.wego.training.domain.TaskMetricsCofiguration;
import com.wego.training.dto.TaskMetricsCofigurationAndRecorderDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

@Mapper
public interface TaskMetricsMapper {

    TaskMetricsMapper INSTANCE = Mappers.getMapper(TaskMetricsMapper.class);
    @Mappings({
            @Mapping(source = "recorder.taskId", target = "taskId"),
    })
    TaskMetricsCofigurationAndRecorderDto toTaskMetricsDto(TaskMetricsCofiguration t, Recorder recorder);
}

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.2.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.4.2.Final</version>
        </dependency>
        <dependency>

你可能感兴趣的:(java)