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
相关产品推荐
相关产品推荐

