簡體   English   中英

如何在現有類中定義新方法並使用 bytebuddy 在同一類中的現有方法中添加對它的調用?

[英]How to define a new method inside an existing class and add a call to it in an existing method inside the same class using bytebuddy?

我有一個看起來像下面的類

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")
  }
}
  1. 首先,這對bytebuddy有可能嗎?
  2. 其次,如果可能,我該怎么做? 我已經了解 bytebuddy 可用於重新定義方法,但不能修改方法體。 這是真的?

如果有人能對此有所了解,那就太好了。 蒂亞!

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");
  }
}

您可以通過Advice.to(HelloAgainAdvice.class)使用此類,而不是MethodDelegation 復制代碼后,您將無法設置斷點,但您重新定義的類將是獨立的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM