Search code examples
javaannotationsbyte-buddy

Generate parameter annotations in Byte Buddy


I would like to use ByteBuddy to generate simple interfaces like this:

public interface MyInterface {
    void myMethod(@Deprecated String myDeprecatedParameter);
}

This is just an example, but the point is that the parameters of the methods need a number of custom annotations. Does anyone have a simple example that would demonstrate how to achieve this in ByteBuddy?


Solution

  • You can create an interface with an annotated parameter like the following. First define the interface name and modifiers, then define the method with it's name, return type and modifiers and finally the parameters and annotations if have any.

    Class<?> myInterface = new ByteBuddy()
            .makeInterface()
            .name("MyInterface")
            .modifiers(Visibility.PUBLIC, TypeManifestation.ABSTRACT)
            .defineMethod("myMethod", void.class, Visibility.PUBLIC)
            .withParameter(String.class, "myDeprecatedParameter")
            .annotateParameter(AnnotationDescription.Builder.ofType(Deprecated.class)
                    .build())
            .withoutCode()
            .make()
            .load(this.getClass().getClassLoader())
            .getLoaded();
    

    You can call annotateParameter(...) many times if you need multiple annotations.

    After the make() method you get the unloaded class, just load the class and use it.

    Here are some prints with the reflection api of the interface class.

    System.out.println(Modifier.toString(myInterface.getModifiers())); // public abstract interface
    System.out.println(myInterface.getSimpleName()); // MyInterface
    System.out.println(Arrays.toString(myInterface.getDeclaredMethods())); // [public abstract void MyInterface.myMethod(java.lang.String)]
    
    Method method = myInterface.getDeclaredMethod("myMethod", String.class);
    System.out.println(method.getName()); // myMethod
    System.out.println(Arrays.toString(method.getParameters())); // [java.lang.String myDeprecatedParameter]
    
    Parameter parameter = method.getParameters()[0];
    System.out.println(parameter); // java.lang.String myDeprecatedParameter
    System.out.println(parameter.getName()); // myDeprecatedParameter
    System.out.println(Arrays.toString(parameter.getAnnotations())); // [@java.lang.Deprecated()]
    
    Annotation annotation = parameter.getAnnotations()[0];
    System.out.println(annotation); // @java.lang.Deprecated()