如何在MapStruct中实现Mapper复用?
MapStruct中复用Mapper的几种方案
针对你提到的基于Spring组件模型的Mapper复用需求,以下是几种实用的实现方案:
方案一:提取公共映射逻辑到基础Mapper
将两个Mapper中重复的映射规则抽离到一个基础Mapper接口,业务Mapper通过继承该接口复用逻辑,便于统一维护。
// 基础Mapper:定义公共映射规则 public interface BaseProductoRepositoryMapper { @BeanMapping(ignoreByDefault = true) @Mapping(source = "convenioResponse.id", target = "id") @Mapping(source = "convenioResponse.cantidad", target = "cantidad") ProductoRepositoryEntity mapConvenioToEntity(ConvenioResponse convenioResponse); } // 原ProductoToRepositoryMapper继承基础Mapper @Mapper(componentModel = "spring") public interface ProductoToRepositoryMapper extends BaseProductoRepositoryMapper { // 复用基础Mapper的方法,也可以保留原有方法名做适配 default ProductoRepositoryEntity map(ConvenioResponse convenioResponse) { return mapConvenioToEntity(convenioResponse); } } // OtherToRepositoryMapper继承基础Mapper,实现自定义转换入口 @Mapper(componentModel = "spring") public interface OtherToRepositoryMapper extends BaseProductoRepositoryMapper { default ProductoRepositoryEntity map(OtherClass otherClass) { // 从OtherClass中获取ConvenioResponse,调用基础映射方法 return mapConvenioToEntity(otherClass.getConvenioResponse()); } }
方案二:直接注入并调用已有Mapper
利用Spring的依赖注入特性,在目标Mapper中注入已有的Mapper实例,直接调用其映射方法。
@Mapper(componentModel = "spring") public interface OtherToRepositoryMapper { // 注入ProductoToRepositoryMapper(Spring环境下MapStruct会自动处理注入) @Autowired ProductoToRepositoryMapper productoToRepositoryMapper; default ProductoRepositoryEntity map(OtherClass otherClass) { // 直接复用已有Mapper的映射逻辑 return productoToRepositoryMapper.map(otherClass.getConvenioResponse()); } }
注意:原ProductoToRepositoryMapper中的INSTANCE字段可以删除,因为Spring会统一管理Bean实例,无需手动通过Mappers.getMapper()获取。
方案三:使用@Mapper的uses属性声明依赖
通过MapStruct原生的uses属性指定当前Mapper依赖的其他Mapper,框架会自动处理实例化与注入,实现映射逻辑复用。
// 移除原ProductoToRepositoryMapper中的INSTANCE字段 @Mapper(componentModel = "spring") public interface ProductoToRepositoryMapper { @BeanMapping(ignoreByDefault = true) @Mapping(source = "convenioResponse.id", target = "id") @Mapping(source = "convenioResponse.cantidad", target = "cantidad") ProductoRepositoryEntity map(ConvenioResponse convenioResponse); } // 使用uses属性声明依赖的Mapper @Mapper(componentModel = "spring", uses = ProductoToRepositoryMapper.class) public interface OtherToRepositoryMapper { // 定义从OtherClass到ConvenioResponse的转换 @Mapping(source = ".", target = ".") ConvenioResponse extractConvenio(OtherClass otherClass); // 复用ProductoToRepositoryMapper的映射方法 default ProductoRepositoryEntity map(OtherClass otherClass) { ConvenioResponse convenioResponse = extractConvenio(otherClass); return map(convenioResponse); } // 该方法会委托给ProductoToRepositoryMapper的实现 ProductoRepositoryEntity map(ConvenioResponse convenioResponse); }
方案选择建议
- 若多个Mapper存在大量重复映射规则,优先选择方案一,统一维护逻辑,降低后续修改成本。
- 若仅需复用单个Mapper的特定方法,方案二更直接,逻辑依赖关系清晰。
- 希望借助MapStruct原生机制管理Mapper依赖时,方案三是更符合框架设计的选择。
内容的提问来源于stack exchange,提问作者sansumng tablet2022
相关产品推荐
相关产品推荐

