【发布时间】: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