2017-09-23 20 views
2

我有一个类,它看起来像下面如何在现有类中定义新方法并使用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?其次,如果可能的话,我该怎么做呢?我明白,bytebuddy可以用来重新定义方法,但不能修改方法体。这是真的?

如果有人能够对此有所了解,那将是一件好事。 TIA!

+0

1)你需要他们称之为重新装订(http://bytebuddy.net/javadoc/1.7.5/net/bytebuddy/ByteBuddy.html#rebase-java.lang.Class-)2)检查他们的教程(http ://bytebuddy.net/#/tutorial),“重新定义和重新定义已存在的类”一节说,除了前面提到的.rebase方法的出发点外,您使用的语法与子类化(他们将详细讨论) 。但是,修改现有的方法似乎不可行,只是修改我认为的现有类。但是,可以替换,但是必须重新构建完整的方法 – tevemadar

+0

谢谢。但是替换整个方法体对我来说不是一种选择,因为我只需访问字节码并且操作字节码非常困难,我希望有一种更简单,更简单的方法修改方法。 – GeekBoy

回答

1

Byte Buddy允许您以各种方式执行此操作。最直接的方法是定义一个实现sayHelloAgain到字节好友创建了一个代表团的拦截:

public class HelloAgainInterceptor { 
    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)使用这个类。随着代码被复制,您将无法设置中断点,但重新定义的类将是自包含的。

相关问题