我有一个类似于下面的课程
public class HelloWorld{
public void sayHelloWorld(){
System.out.println("Hello World");
}
}
现在我想使用bytebuddy向 HelloWorld 类添加另一种方法,并在 sayHelloWorld 中添加对新方法的调用。因此假设在bytebuddy做出它的魔力之后,这个类看起来就像这样。 (我知道bytebuddy适用于字节码而不是java源文件。下面的代码仅用于说明目的。)
public class HelloWorld{
public void sayHelloWorld(){
System.out.println("Hello World");
sayHelloAgain()
}
public void sayHelloAgain(){
System.out.println("Hello Again")
}
}
如果有人能够对此有所了解,那就太好了。 TIA!
答案 0 :(得分:2)
Byte Buddy允许您以各种方式执行此操作。最直接的方法是定义一个实现sayHelloAgain
的拦截器,Byte Buddy创建一个委托:
public class HelloAgainDelegate {
public static void sayHelloAgain() {
System.out.println("Hello again");
}
}
然后,您可以在重新定义的类上定义方法并重新定义sayHelloWorld
方法以首先调用原始方法,然后调用另一个方法:
Class<?> type = new ByteBuddy()
.rebase(HelloWorld.class)
.defineMethod("sayHelloAgain", void.class, Visibility.PUBLIC)
.intercept(MethodDelegation.to(HelloAgainDelegate.class))
.method(named("sayHelloWorld"))
.intercept(SuperMethodCall.INSTANCE
.andThen(MethodCall.invoke(named("sayHelloAgain"))))
.make()
.load(HelloWorld.class.getClassLoader(),
ClassLoadingStrategy.Default.CHILD_FIRST)
.getLoaded();
Object instance = type.newInstance();
type.getMethod("sayHelloWorld").invoke(instance);
type.getMethod("sayHelloAgain").invoke(instance);
在Java代码中,重新定义的类看起来像这样:
public class HelloWorld {
synthetic void sayHelloWorld$origin() {
System.out.println("Hello World");
}
public void sayHelloWorld() {
sayHelloWorld$origin();
sayHelloAgain();
}
public void sayHelloAgain() {
HelloAgainInterceptor.sayHelloAgain();
}
}
如果此选项不适合您,您还可以使用Advice
内联模板类中的代码:
class HelloAgainAdvice {
@Advice.OnMethodExit
static void sayHelloAgain() {
System.out.println("Hello again");
}
}
您可以通过MethodDelegation
使用此类,而不是Advice.to(HelloAgainAdvice.class)
。在复制代码时,您将无法设置断点,但重新定义的类将是自包含的。