微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

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

示例: 我正在使用字节预算来跟踪方法的进入和退出。在执行此操作时,我需要通过阅读注释@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的方法创建单独的建议来解决问题,如下所示:

  @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,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并用它注释您想要代表自定义值的参数。然后,在绑定过程中提供的绑定器负责解析该值,例如返回一个布尔值,该布尔值指示该方法是否带有注释以及具有什么值。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。