如何将(custructor)一个 spring bean 注入到 Mapstruct 的抽象映射器中?

How to inject(custructor) a spring bean into abstract mapper of Mapstruct?

我有下面的映射器 class,我想在其中使用 CounterService。我正在尝试构造函数注入,但它不起作用并且 null 正在打印。

@Mapper(componentModel = "spring", uses = CounterService.class, injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public abstract class CarMapper {

    private CounterService counterService;

    public CarMapper(CounterService counterService) {
       this.counterService = counterService;
    }

    public abstract Car dtoToEntity(CarDto carDto);

    public CarDto entityToDto(Car car) {
        System.out.println(counterService)
        //....
        return carDto;
    }

}

实施 class mapStruct

@Component
public class CarMapperImpl extends CarMapper{

  @Override
  public Car dtoToEntity(CarDto carDto){
    //...
  }
}

如果我使用 @AutoWired 来使用字段注入,那样它就可以正常工作。这意味着 Spring 不支持 abstract class 的构造函数注入。是不是因为abstract class不能直接实例化,需要一个subclass来实例化?
有什么方法 mapStruct 可以在实现 class 中创建构造函数,如:

  public CarMapperImpl(CounterService counterService){
    super(counterService);
  }

这样,构造函数注入应该可以工作。

这与Spring无关。 MapStruct 团队故意决定不使用超级构造函数。

你可以做的是使用 setter 注入。

@Mapper(componentModel = "spring", uses = CounterService.class, injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public abstract class CarMapper {

    private CounterService counterService;

    public abstract Car dtoToEntity(CarDto carDto);

    public CarDto entityToDto(Car car) {
        System.out.println(counterService)
        //....
        return carDto;
    }

    @Autowired
    public void setCounterService(CounterService counterService) {
        this.counterService = counterService;
    }

}

您也可以像下面这样使用 Mapper Decorator。此外,始终确保检查生成的 class.

@DecoratedWith(CarDecoratorMapper.class)
@Mapper(componentModel = "spring")
public interface CarMapper {

    Car dtoToEntity(CarDto carDto);
    CarDto entityToDto(Car car);

}

public abstract class CarDecoratorMapper implements CarMapper {

    @Autowired
    private CarMapper delegate;

    @Autowired
    private CounterService counterService;    

    public Car dtoToEntity(CarDto carDto) {
        Car car = delegate.dtoToEntity(carDto);
        car.setProperty(counterService.count(carDto));
    
        return car;
    }

    public CarDto entityToDto(Car car) {
        CarDto carDto = delegate.entityToDto(car);
        carDto.setProperty(counterService.countDto(car));

        return carDto;
    }
}