问题描述
示例: 我正在使用字节预算来跟踪方法的进入和退出。在执行此操作时,我需要通过阅读注释@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
并用它注释您想要代表自定义值的参数。然后,在绑定过程中提供的绑定器负责解析该值,例如返回一个布尔值,该布尔值指示该方法是否带有注释以及具有什么值。
如果您只想为具有给定批注的方法做事,那么仅将带有批注的方法匹配以应用建议会更有效。