#java #annotations #java-bytecode-asm #byte-buddy
#java #аннотации #java-байт-код-asm #байт-приятель
Вопрос:
Как я могу прочитать аннотацию метода класса Java во время выполнения с помощью ByteBuddy?
Пример: я использую 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 следующим образом:
@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);
}
Ответ №1:
Я понимаю, что вы хотели бы прочитать аннотацию из вашего совета? Вам нужно будет зарегистрировать пользовательскую привязку, которая выдает это значение в качестве результата. Advice
позволяет это с помощью конфигурации:
Advice.withCustomMapping().bind(MyAnnotation.class, ...).to(...)
Все, что вам нужно сделать, это самостоятельно определить аннотацию, установить Retention.RUNTIME
для нее и аннотировать параметр, который вы хотели бы представить своим пользовательским значением. Связующее, которое предоставляется во время привязки, затем отвечает за разрешение этого значения, например, для возврата логического значения, указывающего, аннотирован ли метод и какими значениями.
Однако, если вы хотите выполнять действия только для методов с заданной аннотацией, было бы эффективнее сопоставлять методы только с аннотациями, чтобы применить рекомендации.
Комментарии:
1. Спасибо Рафаэлю за вашу быструю поддержку. Advice.withCustomConfiguration() не существует. Я использую ByteBuddy 1.10.15. Если возможно, можете ли вы предоставить пример фрагмента кода? Мне нужно записывать все входы / выходы методов, и всякий раз, когда присутствует аннотация @Test, записывайте эту дополнительную информацию. Ценю вашу помощь
2. Мой плохой, это
withCustomMapping
.