使用 @Super 委托 bytebuddy 中的私有方法 - 可能吗?
Delegate private method in bytebuddy with @Super - possible?
我正在尝试在 bytebuddy 中委托一个私有方法 - 但如何调用 'overriden' 版本?如果我有
TypePool typepool = TypePool.Default.ofClassPath();
new ByteBuddy()
.rebase(typepool.describe("Foo").resolve(), ClassFileLocator.ForClassLoader.ofClassPath())
.method(named("getNum"))
.intercept(MethodDelegation.to(typepool.describe("FooInterceptor").resolve()))
.make()
.load(typepool.describe("Foo").resolve().getClass().getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
Foo foo1 = new Foo();
System.out.println("Foo says " + foo1.getMessage());
和
public class Foo
{
private int num = 0;
public String getMessage()
{
return "Message is Foo " + getNum();
}
private int getNum()
{
return num++;
}
}
和
import net.bytebuddy.implementation.bind.annotation.Super;
public class FooInterceptor
{
public static int getNum(@Super Foo foo)
{
// This won't work!
return foo.getNum() + 100;
}
}
就编译器而言,即使@Super Foo foo
在运行时要变成别的东西,我也不允许在Foo上调用私有方法。我似乎也无法 reflect/invoke getNum()
- 无论 @Super Foo
变成什么,它似乎都没有 getNum()
方法(尽管它确实有 getMessage()
方法)。
有人能给我指出正确的方向吗?
更新:
@Rafael 的回答在技术上是对我提出的问题的一个很好的解决方案;不幸的是,我想我的例子很糟糕。我认罪。我真正希望的是一个解决方案,它可以让我在传递 getNum()
参数之前对其进行操作。但事实证明,对于我的应用程序,我可能不这样做就可以通过,所以如果情况发生变化,那么我可能会 post 那个确切的例子。
更新 2:
问题完全回答!欢呼!
您可能想使用 @SuperCall Callable
。这将允许您从方法本身调用重写的方法。但是,它不允许您从代理 class.
中调用任何方法
public class FooInterceptor
{
public static int getNum(@SuperCall Callable<Integer> c) throws Exception
{
// This will work!
return c.call() + 100;
}
}
如果您需要操纵参数,可以使用 Morph
注释。它允许您在提供显式参数的同时调用方法:
public interface Morphing<T> {
T invoke(Object[] args);
}
public class FooInterceptor
{
public static int getNum(@Morph Morphing<Integer> m, @AllArguments Object[] args)
{
// This will work!
return m.invoke(args) + 100;
}
}
注意需要显式安装接口:
MethodDelegation.to(FooInterceptor.class)
.appendParameterBinder(Morph.Binder.install(Morphing.class));
我正在尝试在 bytebuddy 中委托一个私有方法 - 但如何调用 'overriden' 版本?如果我有
TypePool typepool = TypePool.Default.ofClassPath();
new ByteBuddy()
.rebase(typepool.describe("Foo").resolve(), ClassFileLocator.ForClassLoader.ofClassPath())
.method(named("getNum"))
.intercept(MethodDelegation.to(typepool.describe("FooInterceptor").resolve()))
.make()
.load(typepool.describe("Foo").resolve().getClass().getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
Foo foo1 = new Foo();
System.out.println("Foo says " + foo1.getMessage());
和
public class Foo
{
private int num = 0;
public String getMessage()
{
return "Message is Foo " + getNum();
}
private int getNum()
{
return num++;
}
}
和
import net.bytebuddy.implementation.bind.annotation.Super;
public class FooInterceptor
{
public static int getNum(@Super Foo foo)
{
// This won't work!
return foo.getNum() + 100;
}
}
就编译器而言,即使@Super Foo foo
在运行时要变成别的东西,我也不允许在Foo上调用私有方法。我似乎也无法 reflect/invoke getNum()
- 无论 @Super Foo
变成什么,它似乎都没有 getNum()
方法(尽管它确实有 getMessage()
方法)。
有人能给我指出正确的方向吗?
更新:
@Rafael 的回答在技术上是对我提出的问题的一个很好的解决方案;不幸的是,我想我的例子很糟糕。我认罪。我真正希望的是一个解决方案,它可以让我在传递 getNum()
参数之前对其进行操作。但事实证明,对于我的应用程序,我可能不这样做就可以通过,所以如果情况发生变化,那么我可能会 post 那个确切的例子。
更新 2:
问题完全回答!欢呼!
您可能想使用 @SuperCall Callable
。这将允许您从方法本身调用重写的方法。但是,它不允许您从代理 class.
public class FooInterceptor
{
public static int getNum(@SuperCall Callable<Integer> c) throws Exception
{
// This will work!
return c.call() + 100;
}
}
如果您需要操纵参数,可以使用 Morph
注释。它允许您在提供显式参数的同时调用方法:
public interface Morphing<T> {
T invoke(Object[] args);
}
public class FooInterceptor
{
public static int getNum(@Morph Morphing<Integer> m, @AllArguments Object[] args)
{
// This will work!
return m.invoke(args) + 100;
}
}
注意需要显式安装接口:
MethodDelegation.to(FooInterceptor.class)
.appendParameterBinder(Morph.Binder.install(Morphing.class));