2015-01-11 111 views
6

假设我有一个方法m可以Byte Buddy访问方法的本地变量名称吗?

public void m() { 
    String foo = "foo"; 
    int bar = 0; 
    doSomething(foo, bar); 
} 

我想用ByteBuddy仪器代码,以便调用mdoSomething时,它会自动把的foobar值成HashMap,相当多的东西看起来像:

public void m() { 
    String foo = "foo"; 
    int bar = 0; 
    context.put("foo", foo); // new code injected 
    context.put("bar", bar); // new code injected 
    doSomething(foo, bar); 
} 

有无论如何通过ByteBuddy做这个仪器?

+0

好,使用ASM,这当然是可能的,但这不是你想要听到的...... – fge

+0

你能否为这种情况提供ASM解决方案? thx ...绿色 –

回答

1

Byte Buddy有内置的方式,以这种方式重新定义方法m。不过,Byte Buddy主动公开了实施Byte Buddy的ASM API。 ASM提供了相当丰富的文档,可以告诉你如何做到这一点。然而,我可以告诉你,这将是相当多的代码。请注意,您需要编译任何启用了调试符号的方法,否则这些内部变量在运行时不可用。

你是否确定要这样做?不知道你的确切用例,感觉这是一个坏主意。通过实现此解决方案,您可以将局部变量的名称作为应用程序的一部分,而不是让它们成为实现细节。

因此,我会建议你采用doSomething方法。请问这就够了yourn什么很容易在字节好友使用类似的拦截做了以下内容:

class Interceptor { 
    void intercept(@Origin Method method, @AllArguments Object[] args) { 
    int index = 0; 
    for(Parameter p : method.getParameters()) { 
     context.add(p.getName(), args[index++]); 
    } 
    } 
} 

那么这个拦截器可以使用如下:

MethodDelegation.to(new Interceptor()).andThen(SuperMethodCall.INSTANCE); 
+0

'doSomething'将采用任意的参数:'void doSomething(Object ... args)'所以我不能用这种方法。这个场景是实现一个Controller方法处理器,所以当用户调用'render(foo,bar)'时,它会自动将'foo'和'bar'放入渲染的参数图中,该参数图在下划线模板视图代码 –

+0

中引用。在这种情况下,你将不得不使用ASM并确保你添加了调试符号。拦截Byte Buddy最小的实体知道是一种方法,我怀疑这将在未来发生变化。您仍然可以使用Byte Buddy提供基础设施,但除此之外您需要使用ASM。 –

相关问题