raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.29k stars 807 forks source link

How to use withParameters to set annotated parameters for methods #1713

Closed cilfm closed 1 month ago

cilfm commented 1 month ago

Hello, when defining class methods, I need to set parameters according to the configuration, and some parameters are annotated. But I found that I couldn't set parameter annotations when using .withParameters() for settings

bytebuddy version: 1.15.2 Here is my test code:

public class ByteBuddyTest {        

    public static void main(String[] args) throws IOException {
        DynamicType.Builder<?> byteBuddy = new ByteBuddy()
                .subclass(Object.class)
                .name("TestController")
                .annotateType(AnnotationDescription.Builder.ofType(RestController.class).build())
                .defineMethod("getList", TypeDescription.Generic.Builder.parameterizedType(ResponseEntity.class, Map.class).build(), Modifier.PUBLIC)
//              .withParameter(TypeDescription.Generic.Builder.of(Integer.class).build(), "state")
//              .annotateParameter(AnnotationDescription.Builder.ofType(PathVariable.class).define("name", "state").build())
                .withParameters(getMethodParameters())
                .intercept(FixedValue.nullValue())
                .annotateMethod(AnnotationDescription.Builder.ofType(GetMapping.class).defineArray("path", new String[] {"/test/api/{state}"}).build());

        DynamicType.Unloaded<?> unload = byteBuddy.make();
        unload.saveIn(new File("G:\\F_Temp\\test"));
        Class<?> controllerClass = unload
                .load(ByteBuddyTest.class.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                .getLoaded();

    }

    private static List<TypeDefinition> getMethodParameters(){
        List<TypeDefinition> params = new ArrayList<>();
        params.add(TypeDescription.Generic.Builder.of(Integer.class)
                .build(AnnotationDescription.Builder.ofType(PathVariable.class).define("name", "state").build(false)));
        params.add(TypeDescription.Generic.Builder.of(Integer.class)
                .annotate(AnnotationDescription.Builder.ofType(PathVariable.class).define("name", "id").build(false))
                .build());      
        params.add(TypeDescription.Generic.Builder.of(Integer.class)
                .build());      
        params.add(TypeDescription.Generic.Builder.of(Long.class)
                .build());      
        params.add(TypeDescription.Generic.Builder.of(String.class)
                .build());      
        return params;
    }
}

If using an unannotated parameter list, it is possible, but if there are annotated parameters, the following error will be reported

Exception in thread "main" java.lang.IllegalStateException: Illegal type annotations on parameter java.lang.Integer arg0 for public org.springframework.http.ResponseEntity TestController.getList(java.lang.Integer,java.lang.Integer,java.lang.Integer,java.lang.Long,java.lang.String)
    at net.bytebuddy.dynamic.scaffold.InstrumentedType$Default.validated(InstrumentedType.java:1760)
    at net.bytebuddy.dynamic.scaffold.MethodRegistry$Default.prepare(MethodRegistry.java:519)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.toTypeWriter(SubclassDynamicTypeBuilder.java:222)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.toTypeWriter(SubclassDynamicTypeBuilder.java:213)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter.make(DynamicType.java:4057)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3741)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3993)
    at com.aecc.plugins.ByteBuddyTest.main(ByteBuddyTest.java:119)
raphw commented 1 month ago

You have to set parameters one by one using withParameter. Then the DSL offers you a way. If the annotations are type annotations, however, you can define them in the type description.

cilfm commented 1 month ago

Thank you very much for your reply. I have already resolved it