如何向 Bytebuddy 中的新方法添加动态数量的带注释参数?

How do I add a dynamic number of annotated parameters to a new method in Bytebuddy?

我正在尝试使用 ByteBuddy 在运行时创建多个 classes。到目前为止,我已经设法创建了 classes,添加了方法并对其进行了注释。这是一个很棒的工具,到目前为止我一直很喜欢使用它。

但现在我卡住了。我有我的 class,有一个方法,有 n 个参数(由配置动态控制)。这有点像...

DynamicType.Builder<?> builder = new ByteBuddy().subclass(Object.class)
                                .name(newClassName)
                                .annotateType(AnnotationDescription.Builder.ofType(Controller.class).build());

// loop for all methods to create
for (final MethodDefinition methodDefinition : methodDefinitions) {

    final List<TypeDefinition> parameters = new ArrayList<>();

    for (final MethodParameterDefinition methodParamDef : methodDefinition.getMethodParameterDefinitions()) {
        parameters.add( TypeDescription.Generic.Builder.rawType(methodParamDef.getType()).build() );
    }

    // define the method
    builder = builder
        .defineMethod(methodDefinition.getName(), outputValueObjectClass, Modifier.PUBLIC)
        .withParameters(parameters)                            
        .annotateMethod(AnnotationDescription.Builder.ofType(RequestMapping.class)
            .defineEnumerationArray("method", RequestMethod.class, RequestMethod.valueOf(methodDefinition.getHttpMethod()))
            .defineArray("path", methodDefinition.getUrl()).build())
        .annotateMethod(AnnotationDescription.Builder.ofType(ResponseBody.class).build())
}

final DynamicType.Unloaded unloadedClass = builder.make();

但是当我尝试使用以下代码向其中一个参数添加注释时...

for (final MethodParameterDefinition methodParamDef : methodDefinition.getMethodParameterDefinitions()) {
    parameters.add( TypeDescription.Generic.Builder.rawType(methodParamDef.getType())
        .annotate(AnnotationDescription.Builder.ofType(PathVariable.class).define("name", methodParamDef.getName()).build())
        .build() );
}

...我得到以下异常....

java.lang.IllegalStateException: Illegal type annotations return type class... 

如果我知道方法参数的数量,我可以使用如下代码添加这些参数...

builder = builder
    .defineMethod(methodDefinition.getName(), outputValueObjectClass, Modifier.PUBLIC)
    .withParameter(methodParameterClass).annotateParameter(AnnotationDescription.Builder.ofType(ModelAttribute.class).build())
    .annotateMethod(AnnotationDescription.Builder.ofType(RequestMapping.class)
        .defineEnumerationArray("method", RequestMethod.class, RequestMethod.valueOf(methodDefinition.getHttpMethod()))
        .defineArray("path", methodDefinition.getUrl()).build())
    .annotateMethod(AnnotationDescription.Builder.ofType(ResponseBody.class).build())

但这不适用于动态方法。

有谁知道如何向方法添加动态数量的参数(带注释)?

提前致谢!

我刚刚检查了代码,由于复制粘贴错误,异常消息具有误导性。错误消息应该告诉您您正在使用不是类型注释的注释来注释类型。

注意代码生成 DSL 中 annotationannotateParameter 之间的区别。前者注解类型,另一个注解参数。这可能看起来令人困惑,因为语法不明确:

void foo(@Bar List<?> qux) { ... }

在Java中都可以表示,如果@Bar是类型注解,则注解List类型,如果是参数注解,则注解参数[=16] =],如果是both,则类型和参数都会被注解。在字节码级别上,您可以选择要注释的元素。但是由于您的注释仅与参数兼容,因此显示了(误导性的,现在已在 master 上修复)错误消息。

如果要添加动态数量的参数,只需 运行 DynamicType.Builder 上的循环并添加如下参数:

MethodDefinition.ParameterDefinition builder = ...
for (...) {
  builder = builder.withParameter(...).annotateParameter(...);
}

这应该可以解决问题。