2017-06-02 1920 views
1

以下是我的上下文:我使用byteBuddy动态生成一个类,该对象基于外部配置将对象转换为另一个对象。我遇到了一些问题,我想找到一个替代方案,就是我发现MapStruct的方式。MapStruct:丰富映射注释以定义自定义映射器

所以我试图构建简单的映射器,我想知道是否有可能定制注释以添加转换函数。比如我想有:

@Mapping(
    source = "mySourceField", 
    sourceType = "String", 
    target = "myTargetField", 
    targetType = "Integer", 
    transformation = {"toInteger", "toSquare"} 
), 

而且所用的mapper实现我会是这样的:

public TypeDest toSiteCatTag(TypeSrc obj) { 

    if (obj == null) { 

     return null; 
    } 

    TypeDest objDest = new TypeDest(); 

    objDest.myTargetField = Formatter.toSquare(
     Formatter.toInteger(obj.mySourceField)); 

    return objDest; 
} 

如果有人能帮助我实现我将不胜感激,它会救我很多时间。

在此先感谢。

+0

在编译期间你有'TypeDest'和'TypeSrc'还是他们是动态类?你是否在运行时生成它们? – Filip

回答

2

如果您的两种类型TypeDestTypeSrc不是在运行时生成的,即它们是您的编译类,那么您可以实现您想要的。 MapStruct在运行时不起作用,因为它是一个Annotation Processor并生成Java代码。如果存在一些问题,比如你试图映射不存在的字段或者存在不明确的映射方法,那么你会得到编译时错误。

它看起来是这样的:

@Mapper 
public interface MyMapper { 

    @Mapping(source = "mySourceField", target = "myTargetField", qualifiedByName = "myTransformation")// or you can use a custom @Qualifier annotation with qualifiedBy 
    TypeDest toSiteCatTag(TypeSrc obj); 

    @Named("myTransformation")// or your custom @Qualifier annotation 
    default Integer myCustomTransformation(String obj) { 
     return Formatter.toSquare(Formatter.toInteger(obj)); 
    } 
} 

有一种方法可以做到这一点,而不在映射定制的方法,但你需要有地方的方法适用的toInteger,然后toSquare改造。如果您有Formatter中的签名Integer squaredString(String obj)的方法。

例如

@Qualifier 
@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.CLASS) 
public @interface SquaredString {} 

public class Formatter { 

    @SquaredString// you can also use @Named, this is just as an example 
    public static Integer squaredString(String obj) { 
     return toSquare(toInteger(obj)); 
    } 
    //your other methods are here as well 
} 

然后你就可以在你的映射器做到这一点:

@Mapper(uses = { Formatter.class }) 
public interface MyMapper { 

    @Mapping(source = "mySourceField", target = "myTargetField", qualifiedBy = SquaredString.class) 
    TypeDest toSiteCatTag(TypeSrc obj); 
} 

上面的例子只会因为qualifedByName/qualified用于应用于特定的映射。如果您想要将String转换为Integer的方法不同,则可以在Mapper中或Mapper#uses中的某些类中定义一种方法,其签名为Integer convertString(String obj)。 MapStruct然后将从StringInteger的转换委托给此方法。

有关映射方法解析的更多信息,您可以在参考文档中找到更多关于映射与限定符herehere的信息。

+0

看起来很完美。非常感谢,你为我节省了很多时间:) – nbchn