繁体   English   中英

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

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

如何在运行时使用 ByteBuddy 读取 Java 类方法注释?

示例:我正在使用 bytebuddy 来跟踪方法进入和退出。 这样做时,我需要通过阅读注释@Test 来知道一个方法是否是单元测试。

  @Test
  public void getBuildByAuthor() {
    .
    .
  }

这是关于我如何记录方法的进入/退出的示例。

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);
  }

更新:我通过为带有注释 @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);
  }

我知道您想从您的建议中阅读注释? 您需要注册一个生成此值作为结果的自定义绑定。 Advice通过配置允许这样做:

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

您需要做的就是自己定义一个注释,为其设置Retention.RUNTIME并用它来注释您想要表示自定义值的参数。 在绑定期间提供的绑定器然后负责解析这个值,例如返回一个布尔值,指示该方法是否被注释以及具有什么值。

如果您只想为具有给定注释的方法做一些事情,那么仅将方法与注释匹配以应用建议会更有效。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM