【问题标题】:How to read a Java class method annotation with ByteBuddy如何使用 ByteBuddy 读取 Java 类方法注解
【发布时间】:2020-10-11 01:27:23
【问题描述】:

如何使用 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);
  }

【问题讨论】:

    标签: java annotations java-bytecode-asm byte-buddy


    【解决方案1】:

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

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

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

    如果您只想对具有给定注释的方法执行操作,那么仅将具有注释的方法匹配以应用建议会更有效。

    【讨论】:

    • 感谢 Rafael 的快速支持。 Advice.withCustomConfiguration() 不存在。我正在使用 ByteBuddy 1.10.15。如果可能的话,你能提供示例代码sn-p吗?我需要记录方法的所有进入/退出,并且只要存在 @Test 注释,就记录该附加信息。感谢您的帮助
    • 我的错,是withCustomMapping
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多