MapStruct 的核心能力通过一系列注解实现,这些注解用于定义映射规则、配置转换行为、处理特殊场景(如字段名不匹配、类型转换等)。以下是最常用的几个注解及其用法:

1. @Mapper

作用:标记一个接口为 MapStruct 的映射接口,MapStruct 会在编译期为该接口生成实现类(包含具体的转换逻辑)。
核心属性

  • componentModel:指定生成的实现类的“组件模型”,用于集成到依赖注入框架(如 Spring、CDI)。常见取值:
    • default:默认值,生成的实现类无特殊注解,需手动实例化(如 UserMapper INSTANCE = Mappers.getMapper(UserMapper.class))。
    • spring:生成的实现类会添加 @Component 注解,可通过 Spring 的 @Autowired 注入。
    • cdi:适用于 CDI 容器,生成的类会添加 @Named 注解。
  • uses:指定当前映射接口依赖的其他映射器(当需要调用其他映射器的方法进行嵌套转换时使用)。
  • unmappedTargetPolicy:配置“目标对象存在未映射字段”时的处理策略(如报错、警告),默认忽略。取值:ERROR(编译报错)、WARN(编译警告)、IGNORE(忽略)。

示例

// 生成 Spring 组件,依赖其他映射器(AddressMapper),未映射字段报错  
@Mapper(  
    componentModel = "spring",  
    uses = AddressMapper.class,  
    unmappedTargetPolicy = ReportingPolicy.ERROR  
)  
public interface UserMapper {  
    // 映射方法...  
}  

2. @Mapping

作用:配置单个字段的映射规则(如源字段与目标字段的对应关系、类型转换方式等),用在映射方法上。
核心属性

  • source:源对象的字段名(如实体类的 userName)。
  • target:目标对象的字段名(如 DTO 的 name),若与 source 同名,可省略。
  • ignore:是否忽略该字段(true 表示不映射该字段)。
  • defaultValue:当源字段为 null 时,目标字段的默认值(如 defaultValue = "unknown")。
  • defaultExpression:更灵活的默认值表达式(基于 Java 表达式),如 defaultExpression = "java(java.time.LocalDate.now())"(默认当前日期)。
  • qualifiedByName:指定用于转换的“命名方法”(配合 @Named 注解,解决同一类型的不同转换逻辑)。
  • dateFormat:日期类型转换的格式(如 dateFormat = "yyyy-MM-dd",将 StringLocalDate 互转)。

示例

@Mapper(componentModel = "spring")  
public interface UserMapper {  

    // 映射 UserEntity 到 UserDTO  
    @Mapping(source = "userName", target = "name") // 字段名不同:userName → name  
    @Mapping(source = "birthday", target = "birthdayStr", dateFormat = "yyyy-MM-dd") // 日期格式化  
    @Mapping(source = "age", target = "age", defaultValue = "0") // 源为null时默认0  
    @Mapping(source = "gender", target = "genderDesc", qualifiedByName = "genderToDesc") // 调用自定义方法  
    @Mapping(source = "password", target = "password", ignore = true) // 忽略密码字段  
    UserDTO entityToDto(UserEntity entity);  
}  

3. @Mappings

作用:当一个映射方法需要配置多个字段的映射规则时,用 @Mappings 包裹多个 @Mapping 注解(Java 8 及以上支持重复注解,可省略 @Mappings,直接写多个 @Mapping)。

示例

// 方式1:用 @Mappings 包裹(兼容旧版本)  
@Mappings({  
    @Mapping(source = "userName", target = "name"),  
    @Mapping(source = "birthday", target = "birthdayStr", dateFormat = "yyyy-MM-dd")  
})  
UserDTO entityToDto(UserEntity entity);  

// 方式2:直接写多个 @Mapping(Java 8+ 支持)  
@Mapping(source = "userName", target = "name")  
@Mapping(source = "birthday", target = "birthdayStr", dateFormat = "yyyy-MM-dd")  
UserDTO entityToDto(UserEntity entity);  

4. @MappingTarget

作用:指定一个“已存在的目标对象”作为转换的目标,MapStruct 会将源对象的字段值更新到该目标对象中(而非创建新的目标对象)。常用于“部分更新”场景(如根据源对象更新目标对象的部分字段)。

示例

@Mapper(componentModel = "spring")  
public interface UserMapper {  

    // 将 entity 的字段更新到已存在的 dto 中(不创建新 dto)  
    @Mapping(source = "userName", target = "name")  
    void updateDtoFromEntity(UserEntity entity, @MappingTarget UserDTO dto);  
}  

// 使用时:  
UserEntity entity = ...; // 源对象(包含最新数据)  
UserDTO existingDto = ...; // 已存在的目标对象(需要更新)  
userMapper.updateDtoFromEntity(entity, existingDto); // existingDto 的字段会被更新  

5. @InheritInverseConfiguration

作用:“继承反向映射规则”,用于简化“双向映射”的配置。例如:若已定义 entityToDto 方法,那么 dtoToEntity 方法可通过该注解自动继承反向的映射规则(无需重复配置 sourcetarget)。

示例

@Mapper(componentModel = "spring")  
public interface UserMapper {  

    // 正向映射:entity → dto  
    @Mapping(source = "userName", target = "name")  
    @Mapping(source = "birthday", target = "birthdayStr", dateFormat = "yyyy-MM-dd")  
    UserDTO entityToDto(UserEntity entity);  

    // 反向映射:dto → entity,继承正向映射的反向规则  
    @InheritInverseConfiguration(name = "entityToDto") // 指定继承哪个方法的反向规则  
    @Mapping(target = "id", ignore = true) // 额外忽略 id 字段(反向映射时不处理)  
    UserEntity dtoToEntity(UserDTO dto);  
}  

上述代码中,dtoToEntity 会自动应用 entityToDto 的反向规则:name → userNamebirthdayStr → birthday(并自动使用 yyyy-MM-dd 解析字符串为日期)。

6. @Named

作用:为“自定义转换方法”命名,配合 @MappingqualifiedByName 属性使用,用于区分同一类型的不同转换逻辑(如同一字段在不同场景下需要不同的转换方式)。

示例

@Mapper(componentModel = "spring")  
public interface UserMapper {  

    // 定义两个不同的日期转换方法(用 @Named 命名)  
    @Named("dateToStrShort")  
    default String dateToStrShort(LocalDate date) {  
        return date.format(DateTimeFormatter.ofPattern("yyyy-MM")); // 短格式:2023-10  
    }  

    @Named("dateToStrLong")  
    default String dateToStrLong(LocalDate date) {  
        return date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); // 长格式:2023-10-01  
    }  

    // 映射时通过 qualifiedByName 指定使用哪个方法  
    @Mapping(source = "birthday", target = "birthdayShort", qualifiedByName = "dateToStrShort")  
    @Mapping(source = "birthday", target = "birthdayLong", qualifiedByName = "dateToStrLong")  
    UserDTO entityToDto(UserEntity entity);  
}  

7. @BeanMapping

作用:配置整个映射方法的全局行为(而非单个字段),如忽略未显式配置的字段、设置映射优先级等。
核心属性

  • ignoreByDefault:是否默认忽略所有未显式配置的字段(true 表示只映射 @Mapping 显式配置的字段)。
  • resultType:指定映射方法的返回类型(当方法返回值是接口/父类时,指定具体实现类)。

示例

@Mapper(componentModel = "spring")  
public interface UserMapper {  

    // 只映射显式配置的字段(其他字段忽略)  
    @BeanMapping(ignoreByDefault = true)  
    @Mapping(source = "userName", target = "name") // 只映射 name 字段  
    @Mapping(source = "age", target = "age") // 只映射 age 字段  
    UserDTO entityToSimpleDto(UserEntity entity);  
}  

8. @ValueMapping

作用:用于枚举类型的映射,指定源枚举值与目标枚举值的对应关系(解决枚举值名称/含义不同的转换)。

示例

// 源枚举  
public enum GenderEntity {  
    MALE, FEMALE, UNKNOWN  
}  

// 目标枚举  
public enum GenderDto {  
    MAN, WOMAN, OTHER  
}  

@Mapper(componentModel = "spring")  
public interface GenderMapper {  

    // 枚举值映射:MALE→MAN,FEMALE→WOMAN,其他值→OTHER  
    @ValueMapping(source = "MALE", target = "MAN")  
    @ValueMapping(source = "FEMALE", target = "WOMAN")  
    @ValueMapping(source = MappingConstants.ANY_REMAINING, target = "OTHER") // 剩余值默认映射到 OTHER  
    GenderDto entityToDto(GenderEntity gender);  
}  

9. @BeforeMapping

作用:用于在映射方法执行前进行预处理操作。它允许开发者对源对象或其他相关数据进行修改、验证等操作,确保映射过程能基于符合预期的数据进行。

10. @AfterMapping

作用:用于在映射方法执行后进行后处理操作。通常用于对映射后的目标对象进行额外的修改、填充等操作,使目标对象更符合业务要求。

总结

MapStruct 的注解围绕“字段映射规则”和“转换行为配置”展开:

  • @Mapper 是基础,定义映射接口和全局配置;
  • @Mapping(及 @Mappings)配置单个字段的映射细节;
  • @MappingTarget 用于更新已有对象,@InheritInverseConfiguration 简化双向映射;
  • @Named + qualifiedByName 处理自定义转换逻辑;
  • @BeanMapping 控制方法级全局行为,@ValueMapping 专门处理枚举映射。

掌握这些注解后,可灵活应对大多数对象转换场景,大幅减少手动编写 getter/setter 的工作量。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐