Añadir método de anotación en tiempo de ejecución con el byte de amigos

lub0v:

He estado buscando la respuesta a "¿cómo añadir una anotación al método en tiempo de ejecución" por varios días ya y encontraron esta increíble herramienta llamada Byte de amigos, jugado con él, pero todavía no puede hacer que funcione mientras que necesito. Estoy seguro de que debe ser capaz de hacer que a partir de esta pregunta Can Byte de Buddy crear campos y anotaciones método en tiempo de ejecución?

Tener esta clase:

public class ClassThatNeedsToBeAnnotated {
  public void method(int arg1, String arg2) {
    // code that we don't want to touch at all, leave it as is
    System.out.println("Called method with arguments " + arg1 + " " + arg2);
  }

  public void method() {
    System.out.println("Called method without arguments");
  }
}

y este código:

 public class MainClass {
      public static void main(String[] args) {
        ByteBuddyAgent.install();

        AnnotationDescription description = AnnotationDescription.Builder.ofType(MyClassAnnotation.class)
            .define("value", "new")
            .build();

        new ByteBuddy()
            .redefine(ClassThatNeedsToBeAnnotated.class)
            .annotateType(description)
            .make()
            .load(ClassThatNeedsToBeAnnotated.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());

      }
}

Es fácil añadir una anotación a la clase . Pero para el método , que parece no ser posible sin cambiar la implementación del método.

Method existingMethod = ClassThatNeedsToBeAnnotated.class.getDeclaredMethods()[0];
AnnotationDescription annotationDescription = AnnotationDescription.Builder.ofType(MyMethodAnnotation.class)
    .build();
new ByteBuddy()
    .redefine(ClassThatNeedsToBeAnnotated.class)
    .annotateType(description)
    .method(ElementMatchers.anyOf(existingMethod))
    // here I don't want to intercept method, I want to leave the method code untouched. How to do that?
    .annotateMethod(annotationDescription)
    .make()
    .load(ClassThatNeedsToBeAnnotated.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());

Estoy seguro de que yo sólo no hago las cosas bien, pero por desgracia no puede encontrar un ejemplo cuando hay ningún cambio de código para el método y el único cambio de anotación.

Rafael Winterhalter:

Encontraste un punto ciego en el byte de amigos que pensé de fijar por un tiempo. Las primeras versiones de Byte de amigos no permitieron anotaciones para definir pero cuando lo hizo, la API fue ya tan ampliamente utilizados que no podía cambiarlo y requeriría algunos bits de la aplicación, también.

Si usted está dispuesto a pagar el precio mínimo de la adición de un método de síntesis, se puede reajustar la clase en su lugar:

new ByteBuddy().rebase(ClassThatNeedsToBeAnnotated.class)

Si lo hace, sólo puede utilizar la API actual y añadir una aplicación de SuperMethodCall. Esto invocará el mismo método en un rebasement.

Esta mejora del byte de amigos se realiza un seguimiento aquí: https://github.com/raphw/byte-buddy/issues/627

ACTUALIZACIÓN : En el próximo byte de amigos 1.10.0 esto es posible gracias a:

new ByteBuddy()
  .redefine(ClassThatNeedsToBeAnnotated.class)
  .visit(new MemberAttributeExtension.ForMethod()
    .annotateMethod(someAnnotation)
    .on(matcher))
  .make();

instancia anotación puede ser conseguir por: AnnotationDescription.Latent.Builder.ofType(AnnotationClass.class).build()

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=231101&siteId=1
Recomendado
Clasificación