如何在MapStruct映射器的实现方法中正确引用其他映射器?
在MapStruct抽象类中正确引用其他映射器的解决方案
问题根源
你在抽象类UserMapper里手动定义了EmailMapper字段和构造方法,但MapStruct生成子类时,并没有把注入的EmailMapper传递给父类构造,导致父类的emailMapper实例为空,调用时会触发空指针异常。这是因为MapStruct默认会为uses属性指定的映射器在子类中生成独立字段,不会自动关联你自定义的父类构造参数。
解决方法
方法1:让MapStruct自动传递构造参数给父类
修改UserMapper,保持字段为private final(或改为protected),确保构造方法参数与uses中的映射器类型一致,MapStruct会自动在生成的子类构造中调用父类构造并传入依赖:
@Mapper(uses = EmailMapper.class, componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR) public abstract class UserMapper { private final EmailMapper emailMapper; protected UserMapper(EmailMapper emailMapper) { this.emailMapper = emailMapper; } public User toUser(UpdateUserRequestDto dto) { User user = new User(); user.setId(dto.getId()); user.setEmailData(emailMapper.toEmailDatas(dto.getEmailData(), user)); return user; } }
此时MapStruct生成的实现类会自动添加super(emailMapper)调用:
@Component public class UserMapperImpl extends UserMapper { @Autowired public UserMapperImpl(EmailMapper emailMapper) { super(emailMapper); // 自动生成父类构造调用,传递依赖 } }
方法2:移除手动构造,改用字段注入
如果可以调整注入策略,将injectionStrategy改为FIELD,在抽象类中声明protected的EmailMapper字段,MapStruct会自动在子类中完成注入,父类直接使用即可:
@Mapper(uses = EmailMapper.class, componentModel = "spring", injectionStrategy = InjectionStrategy.FIELD) public abstract class UserMapper { protected EmailMapper emailMapper; public User toUser(UpdateUserRequestDto dto) { User user = new User(); user.setId(dto.getId()); user.setEmailData(emailMapper.toEmailDatas(dto.getEmailData(), user)); return user; } }
生成的子类会自动注入emailMapper,无需额外处理。
核心注意事项
- 用抽象类+构造注入时,父类构造参数必须和
uses里的映射器类型完全匹配,MapStruct才能识别并自动传递参数。 - 不要在抽象类和生成的子类中重复声明相同的映射器字段,否则会导致父类实例无法正确初始化。
- 如果用构造注入,父类构造方法需设为
protected,确保子类可以调用。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

