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

Spring环境下MapStruct中@uses引入的映射器无法@Autowired初始化问题

问题描述

我定义了一个MapStruct接口ParentMapper,通过@uses注解引入了另外两个MapStruct映射器:

@Mapper(componentModel = "spring", uses = {Mapper1.class, Mapper2.class})
public interface ParentMapper{

}

现在我想在ParentMapper内部引用这两个映射器,以便在自定义的默认方法中使用它们。我尝试通过@Autowired注解注入这两个映射器:

@Autowired
Mapper1 mapper1;

@Autowired
Mapper2 mapper2;

但这种方式不生效,映射器似乎并未初始化。既然这些映射器是由Spring注入的,为何会出现未初始化的情况?

原因与解决方案

原因

你在接口中使用@Autowired标注字段的方式根本不成立:Java接口不能拥有实例字段,你声明的mapper1和mapper2本质上是public static final的常量,而非实例成员。Spring无法为接口的常量注入实例,自然不会初始化这些映射器。

另外,@uses注解的作用是告诉MapStruct:在自动生成的映射逻辑中,若遇到需要转换的类型,可以调用指定Mapper的转换方法,但它不会自动将这些Mapper作为实例成员注入到生成的实现类中。

解决方案

要在自定义默认方法中使用这两个Mapper,需要让MapStruct生成的Spring实现类持有它们的实例,推荐以下两种方式:

1. 构造方法注入(推荐)

在接口中声明构造方法签名,MapStruct会自动生成包含该构造方法的实现类,Spring会通过构造方法注入所需的Mapper实例:

@Mapper(componentModel = "spring", uses = {Mapper1.class, Mapper2.class})
public interface ParentMapper {
    // 声明构造方法,Spring自动注入依赖
    ParentMapper(Mapper1 mapper1, Mapper2 mapper2);

    // 自定义默认方法,直接使用注入的Mapper
    default CombinedDto mapCombined(EntityA a, EntityB b) {
        CombinedDto dto = new CombinedDto();
        dto.setPartA(mapper1.entityToDto(a));
        dto.setPartB(mapper2.entityToDto(b));
        return dto;
    }
}

2. Setter方法注入

如果偏好Setter注入,可在接口中定义抽象Setter方法,MapStruct生成的实现类会实现这些方法,Spring会调用Setter完成依赖注入:

@Mapper(componentModel = "spring", uses = {Mapper1.class, Mapper2.class})
public interface ParentMapper {
    // 抽象Setter方法,Spring注入依赖
    void setMapper1(Mapper1 mapper1);
    void setMapper2(Mapper2 mapper2);

    // 自定义默认方法
    default CombinedDto mapCombined(EntityA a, EntityB b) {
        CombinedDto dto = new CombinedDto();
        dto.setPartA(mapper1.entityToDto(a));
        dto.setPartB(mapper2.entityToDto(b));
        return dto;
    }
}

内容的提问来源于stack exchange,提问作者Luk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:33:39