我看了ByteBuddy的文档,也看了一些使用ByteBuddy的Java代理实现。但我仍然不清楚什么是使用ByteBuddy代理的正确方法。
这是我用来引导代理的代码。
public class ByteBuddyAgent {
public static void premain(String arguments, Instrumentation instrumentation) {
System.out.println("Bootstrapping ByteBuddy Agent");
new AgentBuilder.Default()
.with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
.type(ElementMatchers.hasSuperClass(ElementMatchers.nameContains("Level1")))
.transform(new ByteBuddyTransformer()
.installOn(instrumentation);
}
private static class ByteBuddyTransformer implements AgentBuilder.Transformer{
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module) {
return builder.method(ElementMatchers.named("printLevel"))
.intercept(Advice.to(MethodTracker.class));
}
}
}
这是我的Advice类,我尝试了Advice支持的不同注解,效果很好。
public class MethodTracker {
@Advice.OnMethodEnter
public static Object onMethodBegin(@Advice.This Object invokedObject, @Advice.AllArguments Object[] arguments,
@Advice.FieldValue("name") Object fieldValue, @Advice.Origin Object origin,
@Advice.Local("localVariable") Object localVariable) {
System.out.println("=======on Method Begin Running with ByteBuddy=======, " + invokedObject);
System.out.println("======Printing arguments=======");
for(Object obj: arguments){
System.out.println("Argument:: " + obj);
}
localVariable = "Gunika";
System.out.println("FieldValue:: " + fieldValue);
System.out.println("Origin:: " + origin);
return "ReturningStateFromOnMethodBegin";
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void onMethodEnd(@Advice.This Object invokedObject, @Advice.Return Object returnValue,
@Advice.FieldValue("name") Object fieldValue, @Advice.Enter Object state,
@Advice.Local("localVariable") Object localVariable){
System.out.println("=======on Method End Running with ByteBuddy======= " + invokedObject);
System.out.println("Return value is " + returnValue);
System.out.println("FieldValue:: " + fieldValue);
System.out.println("FieldValue:: " + fieldValue);
System.out.println("State:: " + state);
System.out.println("LocalVariable:: " + localVariable);
}
}
我的问题如下。
现在在我的示例应用中,我只尝试了1条规则的匹配,但如果有 "n "条规则,我想应用什么来实现呢?
有初始的规则集,是应用provided到代理。现在让我们说,在某个时间点,我想添加另一个规则。正确的实现方式是什么?
我们创建的AgentBuilder实例是否应该在Java Agent中只创建一次?
任何其他在使用ByteBuddy代理时应该注意的信息都会有所帮助。
Advice.to(MethodTracker.class)
是相当昂贵的。如果你仪表很多类,又想花费内存,我建议你重用实例,它是不可变的。
别的不说了。@Advice.AllArguments
比使用读取特定参数的专门建议类更昂贵,如果你能负担得起的话。然而,这是一个JVM的问题,而不是Byte Buddy特有的问题。您可以使用 -Dnet.bytebuddy.dump=/some/folder
来查看生成了哪些字节码。昂贵的地方往往在于埋没了你去做什么构造。