【问题标题】:Delegate private method in bytebuddy with @Super - possible?使用@Super 在 bytebuddy 中委托私有方法 - 可能吗?
【发布时间】:2016-10-11 21:56:22
【问题描述】:

我正在尝试在 bytebuddy 中委派一个私有方法 - 但如何调用“覆盖”版本?如果我有

    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 上调用私有方法。我似乎也无法反映/调用getNum() - 无论@Super Foo 变成什么,它似乎都没有getNum() 方法(尽管它确实有getMessage() 方法)。

有人可以在这里指出我正确的方向吗?

更新:

@Rafael 的回答在技术上是对我提出的问题的一个很好的解决方案;不幸的是,我想我的例子很糟糕。过失。我真正希望的是一个解决方案,它可以让我在传递参数之前操纵getNum() 的参数。但事实证明,对于我的应用程序,我可能不这样做就可以过关,所以如果情况发生变化,那么也许我会发布那个确切的例子。

更新 2:

问题已完全回答!欢呼!

【问题讨论】:

    标签: java reflection byte-buddy


    【解决方案1】:

    您可能想使用@SuperCall Callable。这将允许您从方法本身调用被覆盖的方法。但是,它不允许您从代理类中调用任何方法。

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

    【讨论】:

    • 是的 - 我看到了这个,但我希望在将参数传递给方法之前对其进行操作(刚刚意识到这是一个不好的例子,因为getNum() 没有参数!),我的理解是如果我有一个 Callable,它们会被咖喱/锁定在里面。
    • 我更新了我的答案,以展示如何提供明确的论据。
    • 如何在Android中追加ParameterBinder?
    猜你喜欢
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    相关资源
    最近更新 更多