You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在MapStruct接口中自动装配Spring Bean?@Context方法未执行问题

在MapStruct中结合Spring配置Bean使用@BeforeMapping/@AfterMapping

针对你的问题,确实有两种可行的方案来实现需求:抽象类注入Bean和正确使用@Context注解,下面分别详细说明:


方案一:使用抽象类替代接口(你已验证可行,补充完整写法)

这种方式的核心是把MapStruct映射器定义为抽象类,直接通过Spring的@Autowired注入配置Bean,不需要额外传参,非常直观:

1. 抽象映射器类

@Mapper(componentModel = "spring") // 让MapStruct生成Spring管理的Bean
public abstract class MyMapper {

    // 直接注入你的配置类
    @Autowired
    protected PartNumberMapConfiguration partNumberMapConfiguration;

    @Mapping(target = "myTarget.partNumber", ignore = true)
    public abstract MyTarget mapSource2Target(MySource mySource);

    @AfterMapping
    protected void afterMapping(@MappingTarget MyTarget target, MySource source) {
        // 直接使用注入的配置类
        String mappedPartNumber = partNumberMapConfiguration.getPartNumberMap().get(source.getPartKey());
        target.getMyTarget().setPartNumber(mappedPartNumber);
        // 其他后续处理逻辑
    }
}

2. 使用映射器

在Spring组件中直接注入映射器即可使用,不需要手动传配置:

@Service
public class MyService {
    private final MyMapper myMapper;

    @Autowired
    public MyService(MyMapper myMapper) {
        this.myMapper = myMapper;
    }

    public MyTarget convertSource(MySource source) {
        return myMapper.mapSource2Target(source);
    }
}

方案二:修复@Context注解的使用问题(解决你遇到的方法未触发问题)

你遇到的@AfterMapping未触发,大概率是调用映射方法时没有传入@Context标记的参数,或者映射器没有正确用Spring管理。下面是正确的写法:

1. 映射器接口定义

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

    @Mapping(target = "myTarget.partNumber", ignore = true)
    MyTarget mapSource2Target(MySource mySource, @Context PartNumberMapConfiguration partNumberMapConfiguration);

    @AfterMapping
    default void afterMapping(@MappingTarget MyTarget target, MySource source, @Context PartNumberMapConfiguration partNumberMapConfiguration) {
        // 这里可以正常使用配置类
        String mappedPartNumber = partNumberMapConfiguration.getPartNumberMap().get(source.getPartKey());
        target.getMyTarget().setPartNumber(mappedPartNumber);
    }
}

2. 正确调用映射方法

必须在调用时传入PartNumberMapConfiguration实例(可以通过Spring注入后传递):

@Service
public class MyService {
    private final MyMapper myMapper;
    private final PartNumberMapConfiguration partNumberMapConfiguration;

    @Autowired
    public MyService(MyMapper myMapper, PartNumberMapConfiguration partNumberMapConfiguration) {
        this.myMapper = myMapper;
        this.partNumberMapConfiguration = partNumberMapConfiguration;
    }

    public MyTarget convertSource(MySource source) {
        // 关键:调用时必须传入@Context对应的参数
        return myMapper.mapSource2Target(source, partNumberMapConfiguration);
    }
}

为什么你的@AfterMapping没触发?

  • 如果调用mapSource2Target时只传了MySource参数,没传PartNumberMapConfiguration,MapStruct会生成重载方法,但不会触发带@Context的@AfterMapping方法;
  • 确保映射器的componentModel设置为spring,这样Spring会管理映射器实例,避免手动new导致的问题。

两种方案对比

方案优点缺点
抽象类注入Bean调用简单,无需手动传配置参数无法同时实现多个映射器接口(Java单继承)
@Context注解保持接口形式,灵活性更高调用时必须传递@Context参数,稍显繁琐

根据你的业务场景选择即可,如果不需要实现多个接口,抽象类方案会更简洁;如果需要保持接口的灵活性,就用@Context方案并确保调用时传参正确。

内容的提问来源于stack exchange,提问作者du-it

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:41:03