MapStruct 使用教程

一、什么是 MapStruct

MapStruct 核心概念

MapStruc主要特性

二、MapStruct和BeanUtils区别

三、MapStruct的使用方法

  1. 添加依赖

  2. 定义Mapper接口

  3. 使用Mapper

  4. 自定义映射

  5. 映射方法级别的详细配置

  6. 集合映射

  7. 枚举映射

  8. 使用构造函数映射

  9. 嵌套属性映射

  10. 反向映射

  11. 使用装饰器增强Mapper

  12. 映射继承

  13. 使用@BeforeMapping和@AfterMapping进行预处理和后处理

  14. 使用@Context传递上下文参数

  15. 映射更新

  16. 忽略某些字段

  17. 常量映射

  18. 使用@Mappings定义多个映射规则

  19. 使用Builder模式

  20. 默认值映射

  21. 使用@MapperConfig配置全局映射策略

  22. 使用@IterableMapping和@MapMapping处理集合

  23. 使用@MapMapping 注解来处理 Map 类型的映射

  24. 使用@Qualifier自定义映射方法选择

一、什么是 MapStruct
MapStruct 核心概念
MapStruct是一个Java注解处理器,它的主要功能是自动生成类型安全、高性能且无依赖的bean映射代码。这个工具基于“约定优于配置”的原则,极大地简化了Java Bean类型之间的映射实现过程。

在这里插入图片描述
在多层架构的应用中,经常需要在不同的对象模型之间进行转换,例如在持久层的实体和传输层的DTO(Data Transfer Object,数据传输对象)之间。手动编写这种映射代码是一项繁琐且容易出错的任务。MapStruct通过自动化的方式解决了这个问题,它可以在编译时生成映射代码,从而保证了高性能、快速的开发反馈以及严格的错误检查。

具体来说,使用MapStruct时,开发者只需要定义一个接口,并在接口中定义转换方法。然后,MapStruct会自动生成实现这些方法的代码。这些生成的代码使用纯方法调用,因此速度快、类型安全且易于理解。

MapStruc主要特性
1、类型安全:MapStruct在编译时生成映射代码并进行类型检查,如果源对象和目标对象的属性不匹配,会在编译阶段就报错。

2、性能优秀:由于MapStruct在编译时就生成了映射代码,运行时无需通过反射进行属性拷贝,因此性能较高。

3、灵活性:MapStruct支持复杂的映射,如嵌套映射、集合映射、自定义转换规则等。

4、简洁性:MapStruct使用注解来定义映射规则,使得映射规则的定义更加直观和简洁。

5、无依赖:MapStruct不依赖于任何第三方库,可以很容易地集成到任何项目中。

6、集成Spring:MapStruct也可以与Spring框架集成,允许在映射器中注入Spring管理的bean。

使用MapStruct,开发者只需要定义一个接口,并在接口中声明源对象和目标对象之间的映射关系,MapStruct会在编译时自动生成映射实现类。这极大地提高了代码的可读性和可维护性,同时也避免了手动编写繁琐的转换代码。

二、MapStruct和BeanUtils区别
MapStruct和BeanUtils都是Java中常用的对象属性映射工具,但它们在使用方式和性能上有一些区别。

「1、使用方式:」BeanUtils:使用反射机制进行属性拷贝,使用简单,无需写额外的映射代码。 MapStruct:需要定义映射接口,在编译阶段生成映射实现类,使用注解来定义源对象和目标对象之间的映射关系。

「2、性能:」BeanUtils:由于使用了反射机制,性能较低。 MapStruct:在编译阶段就生成了映射代码,运行时无需通过反射进行属性拷贝,因此性能较高。

「3、灵活性和安全性:」BeanUtils:由于是动态映射,如果源对象和目标对象的属性不匹配,可能会在运行时出现错误。 MapStruct:在编译阶段就进行了类型检查,如果源对象和目标对象的属性不匹配,会在编译阶段就报错,提高了类型安全性。另外,也支持复杂的映射,如嵌套映射、集合映射等。

先看一个案例:

@Mapper
public interface CarMapper {
    @BeanMapping(resultType = CarDto.class, ignoreByDefault = true, mappingControl = MappingControl.FILTER)
    @Mapping(target = "color", ignore = true)
    @Mapping(source = "model", target = "modelName")
    @Mapping(condition = "java(source.getAge() >= 18)", target = "isAdult")
    CarDto map(Car car);

我们定义了一个名为CarMapper的映射器接口,并使用了@Mapper注解将它标记为MapStruct映射器。然后,我们在映射方法上使用了@BeanMapping注解,并提供了以下配置: resultType = CarDto.class:指定映射方法的返回类型为CarDto。 ignoreByDefault = true:在目标类型CarDto中忽略所有未映射的属性。 mappingControl = MappingControl.FILTER:如果存在未匹配的属性,过滤它们而不报告错误或警告。

接下来,我们使用了@Mapping注解,对特定属性进行了额外的配置: target = “color”, ignore = true:忽略源对象的color属性,在目标对象CarDto中不进行映射。 source = “model”, target = “modelName”:将源对象的model属性映射到目标对象的modelName属性。 condition = “java(source.getAge() >= 18)”:添加条件判断,只有当源对象的age属性大于等于18时,才进行映射,并将结果映射到目标对象的isAdult属性。

通过这些配置,我们能够灵活地控制映射方法的行为。可以根据需求指定返回类型、忽略属性、设置映射控制策略,并添加条件判断来决定是否执行映射操作.

三、MapStruct的使用方法

  1. 添加依赖
    在你的pom.xml或者build.gradle文件中添加MapStruct的依赖: Maven:
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.0.Final</version>
</dependency>

Gradle:

implementation 'org.mapstruct:mapstruct:1.5.0.Beta1'
  1. 定义Mapper接口
    定义一个Mapper接口,这个接口将包含你想要转换的方法。例如,假设你有两个类,Person和PersonDto,你想要将Person对象转换为PersonDto对象,那么你可以这样定义你的Mapper:

@Mapper
public interface PersonMapper {
    PersonMapper INSTANCE = Mappers.getMapper( PersonMapper.class );

    @Mapping(source = "name", target = "fullName")
    PersonDto personToPersonDto(Person person);
  1. 使用Mapper
    当你已经定义了Mapper接口后,你就可以在你的代码中使用它了:
Person person = new Person("John", "Doe");
PersonMapper mapper = PersonMapper.INSTANCE;
PersonDto personDto = mapper.personToPersonDto(person);
  1. 自定义映射
    在某些情况下,你可能需要自定义字段映射。你可以通过在@Mapping注解中使用expression或qualifiedByName参数来实现这一点

expression: 这个参数允许你使用Java表达式来定义字段映射。这在源和目标字段之间需要一些特定逻辑时非常有用。例如:

@Mapper
public interface OrderMapper {
    @Mapping(target = "orderDate", expression = "java(new java.text.SimpleDateFormat(\"yyyy-MM-dd\").format(order.getCreationDate()))")
    OrderDto orderToOrderDto(Order order);
}

在这个例子中,orderToOrderDto方法将Order的creationDate字段(类型为Date)转换为OrderDto的orderDate字段(类型为String),并且使用了特定的日期格式。

qualifiedByName: 这个参数允许你引用一个具有@Named注解的方法作为自定义的映射逻辑。例如:

Mapper
public interface OrderMapper {
    @Mapping(target = "customerName", source = "customer", qualifiedByName = "fullName")
    OrderDto orderToOrderDto(Order order);

    @Named("fullName")
    default String customerToString(Customer customer) {
        return customer.getFirstName() + " " + customer.getLastName();
    }
}

在这个例子中,orderToOrderDto方法将Order的customer字段(类型为Customer)转换为OrderDto的customerName字段(类型为String),并且使用了customerToString方法来获取全名。

  1. 映射方法级别的详细配置
    从MapStruct 1.5开始,可以使用@BeanMapping注解在MapStruct中用于在映射方法级别提供更详细的配置。这个注解有许多参数可以使用,例如,你可以选择在更新时忽略null值 以下是一些常见的使用场景:

resultType: 这个参数允许你指定映射方法的返回类型。这在目标类型可以是多个实现类时非常有用。 如果目标类型有多个实现类,并且你希望在映射时使用特定的实现类。通过指定resultType,你可以确保生成的映射代码使用正确的目标类型

@BeanMapping(resultType = CarDto.class)
CarDto map(Car car);

qualifiedBy和qualifiedByName: 这两个参数允许你引用一个具有@Qualifier或@Named注解的方法作为自定义的映射逻辑。

@BeanMapping(qualifiedByName = "fullName")
PersonDto personToPersonDto(Person person);

@Named("fullName")
default String customerToString(Customer customer) {
    return customer.getFirstName() + " " + customer.getLastName();
}

ignoreByDefault: 这个参数允许你忽略所有未明确映射的属性。然后,你可以使用@Mapping注解来明确需要映射的属性。

@BeanMapping(ignoreByDefault = true)
@Mapping(target = "name", source = "fullName")
PersonDto personToPersonDto(Person person);

nullValuePropertyMappingStrategy: 这个参数允许你指定当源属性为null时应如何处理目标属性。例如,你可以选择是否在源属性为null时调用目标的setter方法。

@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
PersonDto personToPersonDto(Person person);
  1. 集合映射
    MapStruct也支持集合的映射,你可以很方便地将一个对象的集合转换为另一个对象的集合。
@Mapper
public interface CarMapper {
    List<CarDto> carsToCarDtos(List<Car> cars);
}

在这个例子中,carsToCarDtos方法将List转换为List。

  1. 枚举映射
    MapStruct 的 @ValueMapping 注解是用来映射枚举值的。这个注解只能在 @Mapper 的接口或抽象类中使用。 下面是一个简单的例子,展示了如何使用 @ValueMapping 在两个枚举类型之间进行映射: 首先,我们定义两个枚举类型:
public enum SourceEnum {
    TYPE_A,
    TYPE_B,
    TYPE_C
}

public enum TargetEnum {
    TYPE_X,
    TYPE_Y,
    TYPE_Z
}

然后,我们创建一个映射器接口并使用 @ValueMapping:

@Mapper
public interface EnumMapper {
    @ValueMappings({
        @ValueMapping(source = "TYPE_A", target = "TYPE_X"),
        @ValueMapping(source = "TYPE_B", target = "TYPE_Y"),
        @ValueMapping(source = "TYPE_C", target = "TYPE_Z")
    })
    TargetEnum sourceToTarget(SourceEnum sourceEnum);
}

在上述代码中,我们定义了一个 sourceToTarget 方法,它将 SourceEnum 对象映射到 TargetEnum 对象。@ValueMapping 注解指定了源枚举值到目标枚举值的映射。

此外,MapStruct 还提供了特殊的源/目标值 NULL 和 ANY,可以用于处理源枚举值为 null 或未映射的情况。例如:


@Mapper
public interface EnumMapper {
    @ValueMappings({
        @ValueMapping(source = "TYPE_A", target = "TYPE_X"),
        @ValueMapping(source = "TYPE_B", target = "TYPE_Y"),
        @ValueMapping(source = "TYPE_C", target = "TYPE_Z"),
        @ValueMapping(source = "NULL", target = "TYPE_Z"),
        @ValueMapping(source = "ANY", target = "TYPE_X")
    })
    TargetEnum sourceToTarget(SourceEnum sourceEnum);
}

在这个例子中,如果源枚举值为 null,则目标枚举值为 TYPE_Z;如果源枚举值没有映射(即源枚举有其他值),则目标枚举值为 TYPE_X。

  1. 使用构造函数映射
    从MapStruct 1.5开始,你可以使用构造函数来创建目标对象。你只需要在你的目标类中定义一个合适的构造函数,MapStruct就会自动使用它。

public class CarDto {

    private final String make;
    private final int seatCount;

    public CarDto(String make, int seatCount) {
        this.make = make;
        this.seatCount = seatCount;
    }
    // getters
}

然后在你的Mapper接口中定义映射方法:

@Mapper
public interface CarMapper {
    CarDto carToCarDto(Car car);
}

MapStruct将使用CarDto的构造函数来创建新的CarDto实例。
9. 嵌套属性映射
MapStruct也支持嵌套属性的映射。例如,如果你的Car类有一个Engine属性,你可以这样定义你的Mapper:

@Mapper
public interface CarMapper {
    @Mapping(source = "engine.horsePower", target = "horsePower")
    CarDto carToCarDto(Car car);
}

在这个例子中,carToCarDto方法将Car的engine.horsePower属性映射到CarDto的horsePower属性。

  1. 反向映射
    MapStruct还提供了反向映射的功能。你可以使用@InheritInverseConfiguration注解来创建反向的映射方法:
@Mapper
public interface CarMapper {
    CarDto carToCarDto(Car car);

    @InheritInverseConfiguration
    Car carDtoToCar(CarDto carDto);
}

在这个例子中,carDtoToCar方法是carToCarDto方法的反向映射。

  1. 使用装饰器增强Mapper
    你可以使用装饰器来增强你的Mapper。首先,定义一个装饰器类:
public abstract class CarMapperDecorator implements CarMapper {
    private final CarMapper delegate;
    public CarMapperDecorator(CarMapper delegate) {
        this.delegate = delegate;
    }

    @Override
    public CarDto carToCarDto(Car car) {
        CarDto dto = delegate.carToCarDto(car);
        dto.setMake(dto.getMake().toUpperCase());
        return dto;
    }
}

然后在你的Mapper接口中使用@DecoratedWith注解:

@Mapper
@DecoratedWith(CarMapperDecorator.class)
public interface CarMapper {
    CarDto carToCarDto(Car car);
}
  1. 映射继承
    可以使用@InheritConfiguration注解使一个映射方法继承另一个映射方法的配置。例如:
@Mapper
public interface MyMapper {

    @Mapping(target = "name", source = "name")
    @Mapping(target = "description", source = "description")
    Target sourceToTarget(Source source);

    @InheritConfiguration
    Target updateTargetFromSource(Source source, @MappingTarget Target target);
}

在上述代码中,我们首先定义了一个 sourceToTarget 方法,它将 Source 对象映射到 Target 对象。然后,我们定义了一个 updateTargetFromSource 方法,它接受一个 Source 对象和一个 Target 对象,并使用 @InheritConfiguration 注解来指示 MapStruct 使用 sourceToTarget 方法的映射配置。这意味着 updateTargetFromSource 方法将使用与 sourceToTarget 相同的映射规则。

注意:@InheritConfiguration 会寻找签名(参数数量和类型)最匹配的方法来继承配置,如果有多个匹配的方法,你需要使用 @InheritConfiguration(name=“…”) 来明确指定要继承的方法。

  1. 使用@BeforeMapping和@AfterMapping进行预处理和后处理
    你可以使用@BeforeMapping和@AfterMapping注解来进行映射前后的处理:
@Mapper
public abstract class CarMapper {
    @BeforeMapping
    protected void enrichCar(Car car) {
        car.setMake(car.getMake().toUpperCase());
    }

    @Mapping(source = "numberOfSeats", target = "seatCount")
    public abstract CarDto carToCarDto(Car car);

    @AfterMapping
    protected void enrichDto(Car car, @MappingTarget CarDto carDto) {
        carDto.setSeatCount(car.getNumberOfSeats());
    }
}

在这个例子中,enrichCar方法在映射前被调用,enrichDto方法在映射后被调用。

  1. 使用@Context传递上下文参数
    你可以使用@Context注解来传递上下文参数给映射方法:
@Mapper
public interface OrderMapper {
    @Mapping(target = "customer", source = "entity.customer", qualifiedByName = "fullName")
    OrderDto orderToOrderDto(Order entity, @Context CycleAvoidingMappingContext context);

    @Named("fullName")
    default String customerToString(Customer customer) {
        return customer.getFirstName() + " " + customer.getLastName();
    }
}

在这个例子中,context参数被用于避免循环引用。

  1. 映射更新
    MapStruct允许你将一个对象的属性更新到另一个已存在的对象。例如:
@Mapper
public interface CarMapper {
    @Mapping(source = "numberOfSeats", target = "seatCount")
    void updateCarFromDto(CarDto carDto, @MappingTarget Car car);
}

在这个例子中,updateCarFromDto方法将CarDto的属性更新到已存在的Car对象。

  1. 忽略某些字段
    有时候,你可能想要忽略源对象中的某些字段。你可以使用@Mapping注解的ignore参数来实现这一点:
@Mapper
public interface CarMapper {
    @Mapping(target = "seatCount", ignore = true)
    CarDto carToCarDto(Car car);
}

在这个例子中,carToCarDto方法将忽略Car的seatCount字段。

  1. 常量映射
    @Mapping注解constant属性可以用于将源对象的某个固定值映射到目标对象的属性:
@Mapper
public interface CarMapper {
    @Mapping(target = "carType", constant = "SEDAN")
    CarDto carToCarDto(Car car);
}

在这个例子中,carToCarDto方法将会把CarDto的carType字段设置为"SEDAN",无论Car对象的实际内容如何。

  1. 使用@Mappings定义多个映射规则
    你可以使用@Mappings注解来定义多个映射规则:
@Mapper
public interface CarMapper {
    @Mappings({
        @Mapping(source = "numberOfSeats", target = "seatCount"),
        @Mapping(source = "manufacturingDate", target = "year")
    })
    CarDto carToCarDto(Car car);
}

在这个例子中,carToCarDto方法将Car的numberOfSeats属性映射到CarDto的seatCount属性,将manufacturingDate属性映射到year属性。

  1. 使用Builder模式
    如果你的目标对象使用了Builder模式,MapStruct也能很好地支持。你只需要在@Mapper注解中指定builder的类名:
@Mapper(builder = @Builder(builderClassName = "Builder", buildMethodName = "build"))
public interface CarMapper {
    CarDto carToCarDto(Car car);
}
  1. 默认值映射
    MapStruct也支持默认值映射,你可以使用@Mapping注解的defaultValue参数来实现这一点:
@Mapper
public interface CarMapper {
    @Mapping(target = "seatCount", source = "numberOfSeats", defaultValue = "4")
    CarDto carToCarDto(Car car);
}

在这个例子中,如果Car的numberOfSeats属性为null,那么carToCarDto方法会将CarDto的seatCount字段设置为"4"。

  1. 使用@MapperConfig配置全局映射策略
    @MapperConfig 注解在 MapStruct 中用于定义全局或共享的映射配置。这个注解可以被应用在接口或抽象类上,然后其他的 @Mapper 可以通过 config 属性引用这个配置。 下面是一个简单的例子: 首先,我们定义一个全局的映射配置:
@MapperConfig(componentModel = "spring", uses = DateMapper.class)
public interface GlobalMapperConfig {
}

在这个例子中,我们指定了 componentModel 为 “spring”,这意味着生成的映射器将是 Spring 的组件,可以使用 @Autowired 进行注入。我们还指定了 uses 属性为 DateMapper.class,这意味着所有引用这个配置的映射器都可以使用 DateMapper 中定义的方法进行映射。 然后,我们创建一个映射器并引用这个全局配置:

@Mapper(config = GlobalMapperConfig.class)
public interface MyMapper {
    // mapping methods
}

在这个例子中,MyMapper 将继承 GlobalMapperConfig 中定义的所有配置。 注意,如果 @Mapper 和 @MapperConfig 中都定义了相同的属性,那么 @Mapper 中的属性将会覆盖 @MapperConfig 中的属性。

@MapperConfig 是一种强大的工具,可以帮助你减少重复的配置,并使你的代码更易于维护

  1. 使用@IterableMapping和@MapMapping处理集合
    当处理集合和映射时,你可能需要特定的转换规则。@IterableMapping 注解的作用是定义一个方法,用于将一个 Iterable 类型的源对象集合映射为目标对象集合。

具体来说,@IterableMapping 注解用于标记一个接口方法,该方法的参数类型为源对象集合,返回类型为目标对象集合。在生成的映射代码中,MapStruct 会将每个源对象映射为一个目标对象,并将它们添加到目标对象集合中。需要注意的是,源对象集合和目标对象集合的元素类型可以不同,此时需要手动指定元素类型转换方式。

@IterableMapping 注解还有一些属性,用于配置映射的行为,例如: qualifiedBy:用于指定一个限定符注解,当存在多个映射器时,可以使用该属性来选择特定的映射器。 elementTargetType:用于指定目标对象集合的元素类型。 nullValueMappingStrategy:用于处理源对象集合中包含空对象或者 null 值的情况。 一个示例的 @IterableMapping 注解的使用方式如下所示:

@Mapper
public interface UserMapper {
    @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
    List<UserDTO> toUserDTOList(Iterable<User> users);
}

上述代码中,UserMapper 接口中的 toUserDTOList 方法使用了 @IterableMapping 注解,用于将 User 集合转换为 UserDTO 集合。其中,nullValueMappingStrategy 属性指定当源对象集合中包含空对象或者 null 值时,返回默认值。

  1. 使用@MapMapping 注解来处理 Map 类型的映射
    @MapMapping 注解用于方法级别,指示 MapStruct 如何映射 Map 类型的属性。你可以在映射器接口中的方法上使用该注解,并提供一些配置选项。
@Mapper
public interface CarMapper {
    @MapMapping(keyTargetType = String.class, valueTargetType = CarDto.class)
    Map<String, CarDto> carsToCarDtos(Map<String, Car> cars);
}

在这个示例中,我们定义了一个名为 CarMapper 的映射器接口,并使用了 @Mapper 注解将它标记为 MapStruct 映射器。

然后,我们在 carsToCarDtos 方法上使用了 @MapMapping 注解,并提供了以下配置选项:

keyTargetType = String.class:指定目标键类型为 String。这会告诉 MapStruct 将源 Map 的键映射为 String 类型。 valueTargetType = CarDto.class:指定目标值类型为 CarDto。这会告诉 MapStruct 将源 Map 的值映射为 CarDto 类型。 通过这样配置 @MapMapping 注解,MapStruct 将自动生成适当的映射代码,按照指定的映射规则将源 Map 中的键值对映射到目标 Map。

需要注意的是,如果你的映射逻辑更加复杂,可以在 @MapMapping 注解的方法参数中提供自定义的转换器。例如:

@Mapper
public interface CarMapper {
    @MapMapping(keyTargetType = String.class, valueTargetType = CarDto.class,
                keyQualifiedBy = {ToUpperCase.class}, valueQualifiedBy = {ConvertValue.class})
    Map<String, CarDto> carsToCarDtos(Map<String, Car> cars);

    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface ToUpperCase {
    }

    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface ConvertValue {
        Class<?> targetType();
    }

    @ToUpperCase
    public String toUpperCase(String key) {
        return key.toUpperCase();
    }

    @ConvertValue(targetType = CarDto.class)
    public CarDto convertValue(Car car) {
        // Custom conversion logic
        return new CarDto(car.getMake(), car.getNumberOfSeats());
    }
}

在这个示例中,我们添加了自定义的转换器。通过使用 keyQualifiedBy 和 valueQualifiedBy 参数,我们可以指定用于键和值的转换器。

我们定义了两个自定义的限定符注解 @ToUpperCase 和 @ConvertValue,并在转换器方法上使用它们。然后,在 carsToCarDtos 方法上分别指定了这两个限定符注解。

这样,当 MapStruct 遇到需要转换键或值的情况时,它将使用相应的转换器方法来进行转换。

  1. 使用@Qualifier自定义映射方法选择
    @Qualifier 注解用于标识自定义转换器方法和映射过程中的限定符。 通过使用 @Qualifier 注解,你可以为转换器方法或映射方法提供更具体的选择标准,以决定哪个方法应该被调用。

下面是一个示例,展示了如何在 MapStruct 1.5 中使用 @Qualifier 注解:

@Mapper
public interface CarMapper {
    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface FastCar {}

    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface ElectricCar {}

    // 转换器方法1
    @FastCar
    CarDto convertToFastCarDto(Car car);

    // 转换器方法2
    @ElectricCar
    CarDto convertToElectricCarDto(Car car);

    // 映射方法
    @Mapping(target = "carDto", qualifiedBy = {FastCar.class, ElectricCar.class})
    GarageDto mapGarageToDto(Garage garage);
}

在这个示例中,我们定义了两个注解 @FastCar 和 @ElectricCar,它们都是通过 @Qualifier 注解来定义的。这些注解用于标识转换器方法 convertToFastCarDto 和 convertToElectricCarDto。

然后,在映射方法 mapGarageToDto 上,我们使用了 qualifiedBy 参数来标记多个限定符。通过这样配置,MapStruct 将根据指定的限定符选择适当的转换器方法来进行映射。

请注意,@Qualifier 注解需要与自定义转换器方法一起使用。你可以根据实际需求定义自己的限定符注解,并将其应用于合适的转换器方法上。

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值