如何在不将其作为方法参数传递的情况下向 POJO class 提供转换器服务

How to provide converter service to POJO class without passing it as method argument

我有 ShoppingList 服务负责生成购物清单,还有一个 IngredientConverter 服务是转换对象的帮助工具。我当前的实现如下所示

@Service
@AllArgsConstructor
public class ShoppingListService {

    private final RecipeService recipeService;
    private final IngredientConverter ingredientConverter;

    public ShoppingList generateShoppingList(List<UUID> uuidsOfRecipes) {
        List<Recipe> recipes = recipeService.getAllByIDIn(uuidsOfRecipes);
        ShoppingList shoppingList = ShoppingList.empty();

        for (Recipe recipe : recipes) {
            shoppingList.addIngredients(recipe.getIngredients());
        }
        shoppingList.finishAddition(ingredientConverter);

        return shoppingList;
    }

}
@RequiredArgsConstructor
public class ShoppingList {

    @Getter
    private final List<IngredientQuantity> optimizedList;
    private final Map<Ingredient, Integer> ingredientAmountMap;

    public static ShoppingList empty() {
        return new ShoppingList(new ArrayList<>(), new HashMap<>());
    }

    public void addIngredients(List<IngredientQuantity> ingredients) { ... }

    public void addIngredient(IngredientQuantity ingredientQuantity) { ... }

    public void finishAddition(IngredientConverter ingredientConverter) {
        for (Ingredient ingredient : ingredientAmountMap.keySet()) {
            IngredientQuantity ingredientQuantity = ingredientConverter.convertWithAmount(
                    ingredient.getName(),
                    ingredientAmountMap.get(ingredient),
                    ingredient.getUnit());

            optimizedList.add(ingredientQuantity);
        }
    }
}
@Service 
public class IngredientConverter {

    public IngredientQuantity convertWithAmount(String name, int amount, Unit unit) { ... }
}

是否有更好的策略为这个 class 提供 IngredientConverter 服务?尽管 ShoppingList 是 POJO class,我能以某种方式自动装配它吗? ShoppingList 是否应该标记为组件?不确定什么是最好的方法。

您不能将服务 class 自动装配到 POJO 中。 Autowire 只能在 spring 托管 classes 内完成。我可以看到 ShoppingList 不是 spring 管理的 class。添加 @Component 也不是理想的解决方案。 AFAIK,此处使用的最佳解决方案是 mapStruct。 mapStruct 可用于在实体和 POJO 之间映射字段。如果任何字段必须单独计算,您可以编写自定义逻辑和自动装配服务。以下是步骤

  1. 将 mapStruct 库添加到 pom.xml
  2. 将下面的映射器 class 添加到您的项目中。 componentModel="spring" 告诉系统这个映射器由 spring.
  3. 管理
  4. 将自动映射所有具有相同名称的字段。
  5. 对于需要转换的字段,可以写@BeforeMapping
Mapper(componentModel="spring")
public abstract class ShoppingListMapper 
{
    @Autowired
    IngredientConverter ingredientConverter; //autowire method you use.
    
    public abstract shoppingListToShoppingListDTO(ShoppingList shoppingList) throws Exception;
    public abstract List<ShoppingList> mapShoppingListsToDTOs(List<ShoppingList> shoppingLists) throws Exception;
    
    @BeforeMapping
    public void convertLogic(ShoppingList la, @MappingTarget ShoppingListDTO slDto) throws Exception 
    {
        //your logic to set required shoppinglist field using converter
    }
    
}

如果这个例子不清楚,可以参考web各种mapstruct的例子。如果您需要进一步的帮助,请告诉我