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

MapStruct自定义枚举映射策略中,如何通过注解处理器的TypeElement获取枚举的domainId属性值?

MapStruct自定义枚举映射策略中,如何通过注解处理器的TypeElement获取枚举的domainId属性值?

嘿,我来帮你搞定这个问题!首先得指出你代码里的一个小问题——getEnumValue方法的返回类型写错啦,应该是Element(具体是VariableElement,因为枚举常量属于变量元素),而不是ElementKind,毕竟我们要操作的是枚举常量实例本身,不是它的类型标识。

接下来,咱们来说说怎么获取domainId的值。你的枚举类是通过构造函数传入domainId的(比如ExampleEnum.A("1")),所以我们可以通过解析枚举常量的初始化表达式来提取构造参数的值,这是编译时注解处理器里最直接的方式。

下面是修正并完善后的代码:

首先修正getEnumValue方法:

protected VariableElement getEnumValue(TypeElement enumTypeElement, String enumConstant) {
    return enumTypeElement.getEnclosedElements().stream()
        .filter(it -> it.getKind() == ElementKind.ENUM_CONSTANT)
        .filter(it -> it.getSimpleName().contentEquals(enumConstant))
        .map(VariableElement.class::cast)
        .findFirst()
        .orElse(null);
}

然后完善getCustomEnumConstant方法,解析初始化表达式拿到domainId:

// 注意:需要让你的策略类能拿到ProcessingEnvironment,MapStruct会自动注入这个对象
private final ProcessingEnvironment processingEnv;

public CustomEnumMappingStrategy(ProcessingEnvironment processingEnv) {
    this.processingEnv = processingEnv;
}

protected String getCustomEnumConstant(TypeElement enumTypeElement, String enumConstant) {
    VariableElement enumConstantElement = getEnumValue(enumTypeElement, enumConstant);
    if (enumConstantElement == null) {
        return super.getEnumConstant(enumTypeElement, enumConstant);
    }

    // 获取枚举常量的初始化表达式(比如A("1")对应的构造调用表达式)
    Expression initializer = enumConstantElement.getInitializer();
    if (initializer instanceof MethodInvocationTree) {
        MethodInvocationTree constructorInvocation = (MethodInvocationTree) initializer;
        // 你的枚举构造函数只有一个String参数,直接取第一个参数
        if (!constructorInvocation.getArguments().isEmpty()) {
            Expression arg = constructorInvocation.getArguments().get(0);
            if (arg instanceof LiteralTree) {
                LiteralTree literal = (LiteralTree) arg;
                // 返回构造参数的字符串值,也就是domainId(注意去掉字符串引号)
                return literal.getValue().toString().replace("\"", "");
            }
        }
    }

    // 如果上面的方式失败, fallback到查找domainId字段的常量值(适合字段被直接赋值的场景)
    VariableElement domainIdField = enumTypeElement.getEnclosedElements().stream()
            .filter(it -> it.getKind() == ElementKind.FIELD)
            .filter(it -> "domainId".equals(it.getSimpleName().toString()))
            .map(VariableElement.class::cast)
            .findFirst()
            .orElse(null);

    if (domainIdField != null) {
        Object constantValue = processingEnv.getElementUtils().getConstantValue(domainIdField);
        return constantValue != null ? constantValue.toString() : null;
    }

    // 都不行的话,用默认策略兜底
    return super.getEnumConstant(enumTypeElement, enumConstant);
}

关键点说明:

  1. 初始化表达式解析:枚举常量的定义(比如A("1"))本质是调用构造函数的语法糖,通过getInitializer()可以拿到这个构造调用的语法树,进而提取参数值。
  2. ProcessingEnvironment注入:MapStruct在初始化自定义策略时,会自动传入ProcessingEnvironment实例,只要你的构造函数声明了这个参数即可使用。
  3. fallback方案:如果枚举类的domainId是直接赋值的(而非构造传入),可以通过查找字段并获取常量值的方式兜底。

最后别忘了在你的Mapper接口上指定这个自定义策略:

@Mapper(enumMappingStrategy = CustomEnumMappingStrategy.class)
public interface YourMapper {
    // 你的映射方法
}

备注:内容来源于stack exchange,提问作者Cilenco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 11:57:59