简体   繁体   English

如何使用 ByteBuddy 读取 Java 类方法注释

[英]How to read a Java class method annotation with ByteBuddy

How can I read Java class method annotation at runtime with ByteBuddy?如何在运行时使用 ByteBuddy 读取 Java 类方法注释?

Example: I am using bytebuddy to track method enter and exit.示例:我正在使用 bytebuddy 来跟踪方法进入和退出。 While doing this, I need to know whether a method is unit test by reading the annotation @Test.这样做时,我需要通过阅读注释@Test 来知道一个方法是否是单元测试。

  @Test
  public void getBuildByAuthor() {
    .
    .
  }

Here is a sample on how I am recording enter/exit of methods.这是关于我如何记录方法的进入/退出的示例。

public class MethodTracer {

  @Advice.OnMethodEnter(inline = false)
  public static Item enter(@Advice.Origin("#t") String type,
                                @Advice.Origin("#m") String method,
                                @Advice.Origin("#s") String signature)
  {
    //TODO: is this Unit test method identified by @Test ?
    return Tracer.enter(type, method, signature);
  }

  @Advice.OnMethodExit(inline = false, onThrowable = Throwable.class)
  public static void exit(@Advice.Enter Item item) {
    Tracer.exit(item);
  }
}
  @Override
  public void instrument(Instrumentation instrumentation) {
    final Advice methodAdvice = Advice.to(MethodTracer.class);
    final Advice constructorAdvice = Advice.to(ConstructorTracer.class);


    ResettableClassFileTransformer agent = new AgentBuilder.Default()
        .with(new TracerLogger())  
        .type(ElementMatchers.nameStartsWith("com.examples.")) 
        .transform(new AgentBuilder.Transformer() {
          @Override
          public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
            builder = builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().method(ElementMatchers.isMethod(), methodAdvice));
            builder = builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().constructor(ElementMatchers.isConstructor(), constructorAdvice));
            return builder;
          }
        })
        .installOn(instrumentation);
  }

Update: I solved the problem by creating separate Advice for methods with annotation @Test as follows:更新:我通过为带有注释 @Test 的方法创建单独的 Advice 解决了这个问题,如下所示:

  @Override
  public void instrument(Instrumentation instrumentation) {
    final Advice methodAdvice = Advice.to(MethodTracer.class);
    final Advice testMethodAdvice = Advice.to(TestMethodTracer.class);
    final Advice constructorAdvice = Advice.to(ConstructorTracer.class);
    final Advice testConstructorAdvice = Advice.to(TestConstructorTracer.class);


    ResettableClassFileTransformer agent = new AgentBuilder.Default()
        .with(new TracerLogger())
            .type(ElementMatchers.nameStartsWith("com.examples.")) 
            .transform(new AgentBuilder.Transformer() {
          @Override
          public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
              builder = builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().method(ElementMatchers.isMethod().and(ElementMatchers.isAnnotatedWith(Test.class)), testMethodAdvice));
              builder = builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().method(ElementMatchers.isMethod().and(ElementMatchers.not(ElementMatchers.isAnnotatedWith(Test.class))), methodAdvice));
              builder = builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().constructor(ElementMatchers.isConstructor().and(ElementMatchers.isAnnotatedWith(Test.class)), testConstructorAdvice));
              builder = builder.visit(new AsmVisitorWrapper.ForDeclaredMethods().constructor(ElementMatchers.isConstructor().and(ElementMatchers.not(ElementMatchers.isAnnotatedWith(Test.class))), constructorAdvice));

              return builder;
          }
        })
        .installOn(instrumentation);
  }

I understand it that you would like to read an annotation from your advice?我知道您想从您的建议中阅读注释? You'd need to register a custom binding that produces this value as its result.您需要注册一个生成此值作为结果的自定义绑定。 Advice allows this by a configuration: Advice通过配置允许这样做:

Advice.withCustomMapping().bind(MyAnnotation.class, ...).to(...)

All you need to do is to define an annotation yourself, set Retention.RUNTIME for it and annotate the parameter you'd like to represent your custom value with it.您需要做的就是自己定义一个注释,为其设置Retention.RUNTIME并用它来注释您想要表示自定义值的参数。 The binder that is supplied during the binding is then responsible to resolve this value, for example to return a boolean that indicates if the method is annotated and with what values.在绑定期间提供的绑定器然后负责解析这个值,例如返回一个布尔值,指示该方法是否被注释以及具有什么值。

If you only want to do things for methods with a given annotation, it would however be more efficient to only match methods with the annotations to apply the advice.如果您只想为具有给定注释的方法做一些事情,那么仅将方法与注释匹配以应用建议会更有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ByteBuddy-在Java代理中读取类注释 - ByteBuddy - Read class annotations in a java agent 如何使用 ASM 读取 Java class 方法注释值 - How to read a Java class method annotation value with ASM ByteBuddy:如何在另一个类中使用自定义方法声明一个类 - ByteBuddy: How to declare a class with a custom method inside another class ByteBuddy 是否可以拦截由带有注释的接口声明的方法? - Is it possible with ByteBuddy to intercept a method that is declared by an interface with an annotation? 如何在ByteBuddy中向类添加字段并在方法拦截器中设置/获取该值 - How to add a field to a class in ByteBuddy and set / get that value in a method interceptor 如何使用ByteBuddy委托拦截bootstrap类方法 - How to use ByteBuddy delegation for intercepting bootstrap class method 阅读通用类Java的注释 - Read annotation of generic class Java Bytebuddy:如何生成本地方法? - Bytebuddy: How to generate a native method? 如何在现有类中定义新方法并使用 bytebuddy 在同一类中的现有方法中添加对它的调用? - How to define a new method inside an existing class and add a call to it in an existing method inside the same class using bytebuddy? 如何使用 java / kotlin 中的注释处理将方法附加到现有类? - How to append a method to existing class using annotation processing in java / kotlin?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM