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

如何在OpenRewrite中为注解添加数组参数?

给@Import注解动态添加数组参数的实现方案

我正在编写自定义OpenRewrite Recipe,目标是给@Import注解的数组参数动态添加多个配置类,期望最终生成的代码效果如下:

@Import({
    TestConfiguration.class,
    XyzConfiguration.class,
    AbcConfiguration.class,
    ...
})

目前我已经能给类添加新注解,但不知道如何为@Import注解添加数组形式的参数,现有代码如下:

private static class ImportVisitor extends JavaIsoVisitor<ExecutionContext> {

    private static final String IMPORT_ANNOTATION = "Import";
    private static final String SPRING_BOOT_APPLICATION_ANNOTATION = "SpringBootApplication";

    @Override
    public @NonNull ClassDeclaration visitClassDeclaration(
            @NonNull ClassDeclaration classDecl,
            @NonNull ExecutionContext executionContext
    ) {
        boolean isApplication = classDecl.getSimpleName().contains("Application");
        boolean isImport = classDecl.getAllAnnotations()
                .stream()
                .anyMatch(annotation -> IMPORT_ANNOTATION.equals(annotation.getSimpleName()));

        if (isApplication && !isImport) {
            List<Annotation> annotations = classDecl.getAllAnnotations();
            Annotation importAnnotation = createAnnotation(IMPORT_ANNOTATION);

            annotations.add(importAnnotation);
            annotations.add(createAnnotation(SPRING_BOOT_APPLICATION_ANNOTATION).withPrefix(Space.format("\n")));

            classDecl = classDecl.withPrefix(Space.format("\n"))
                    .withLeadingAnnotations(annotations);

            maybeAddImport("org.springframework.boot.autoconfigure.SpringBootApplication", false);
            maybeAddImport("org.springframework.context.annotation.Import", false);
        }

        return classDecl;
    }

    public static J.Annotation createAnnotation(String annotation) {
        return new J.Annotation(UUID.randomUUID(),
            Space.EMPTY,
            Markers.EMPTY,
            TypeTree.build(annotation),
            null);
    }
}

解决方案

要实现给@Import添加数组参数,需要改造注解创建逻辑,构建包含数组初始化器的注解参数:

  1. 改造createAnnotation方法,支持传入注解参数
    修改createAnnotation方法,允许接收J.Expression类型的参数,用来构建注解的参数部分:
public static J.Annotation createAnnotation(String annotationName, J.Expression argument) {
    J.Annotation.Arguments args = null;
    if (argument != null) {
        args = new J.Annotation.Arguments(
            UUID.randomUUID(),
            Space.EMPTY,
            List.of(new J.Annotation.Argument(
                UUID.randomUUID(),
                Space.EMPTY,
                null, // @Import的参数默认是value,可省略参数名
                argument,
                Space.EMPTY
            ))
        );
    }
    return new J.Annotation(
        UUID.randomUUID(),
        Space.EMPTY,
        Markers.EMPTY,
        TypeTree.build(annotationName),
        args
    );
}
  1. 构建@Import需要的数组参数并更新业务逻辑
    在visitClassDeclaration方法中,定义要添加的配置类列表,用J.ArrayInitializer构建数组元素(每个元素对应配置类的类型字面量),再创建带参数的@Import注解:
if (isApplication && !isImport) {
    List<Annotation> annotations = classDecl.getAllAnnotations();

    // 定义需要添加的配置类全限定名
    List<String> configClasses = List.of(
        "com.example.TestConfiguration",
        "com.example.XyzConfiguration",
        "com.example.AbcConfiguration"
    );

    // 构建数组元素:生成XXConfiguration.class格式的类型字面量
    List<J.Expression> arrayElements = configClasses.stream()
        .map(className -> {
            maybeAddImport(className, false); // 自动添加配置类的import语句
            return new J.TypeApply(
                UUID.randomUUID(),
                Space.EMPTY,
                TypeTree.build(className),
                new J.TypeArgumentList(UUID.randomUUID(), Space.EMPTY, List.of())
            ).withSuffix(Space.EMPTY);
        })
        .collect(Collectors.toList());

    // 构建带格式的数组初始化器
    J.ArrayInitializer arrayInitializer = new J.ArrayInitializer(
        UUID.randomUUID(),
        Space.format(" "),
        new J.LCurly(UUID.randomUUID(), Space.format("\n    ")),
        arrayElements.stream()
            .map(elem -> elem.withSuffix(Space.format(",\n    ")))
            .collect(Collectors.toList()),
        new J.RCurly(UUID.randomUUID(), Space.format("\n"))
    );

    // 创建带数组参数的@Import注解
    Annotation importAnnotation = createAnnotation(IMPORT_ANNOTATION, arrayInitializer);

    annotations.add(importAnnotation);
    annotations.add(createAnnotation(SPRING_BOOT_APPLICATION_ANNOTATION).withPrefix(Space.format("\n")));

    classDecl = classDecl.withPrefix(Space.format("\n"))
            .withLeadingAnnotations(annotations);

    maybeAddImport("org.springframework.boot.autoconfigure.SpringBootApplication", false);
    maybeAddImport("org.springframework.context.annotation.Import", false);
}

关键说明

  • J.TypeApply用于生成XXConfiguration.class这种类字面量,对应Java中的类字面量语法。
  • J.ArrayInitializer用来构建数组初始化块,通过设置空格和换行符保证生成的代码格式整洁规范。
  • 注解参数通过J.Annotation.Arguments和J.Annotation.Argument构建,@Import的默认参数为value,可以省略参数名。

内容的提问来源于stack exchange,提问作者dk1337

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:32:48