有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

bytebuddy中的java委托私有方法是否带有@Super-mable?

我试图在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:

问题完全回答了!万岁


共 (1) 个答案

  1. # 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));