在 Bytebuddy 中进行现场方法委托和投射

Method delegation on field and cast in Bytebuddy

使用 Bytebuddy 假设以下情况:

class Service {
    protected Handler handler;
...
}

interface Handler {
   public void handle();
}

class ConcreteHandler implements Handler {
    public void handle() {
       ...
    }
    public void handle2() {
       ...
    }
}

一般我们调用Handler的handle()方法,但有些情况下需要调用ConcreteHandler的class的handle2()方法,也就是运行时。现在的问题是:可以使用 Bytebuddy 吗?可能是,但如何?

我试过了:

if (condition) {
    MethodCall methodCall = (MethodCall) 
        MethodCall.invoke(methodHandle2).onField("handler")
                        .withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC);
}

... 但它因 IllegalStateException 而失败:无法调用 public void com.framework.ConcreteHandler.handle2(...) on protected com.framework.Handler com.framework.Service.handler

有什么想法吗?

如果您的字段变量是 Handler,您不能调用 handle2(),因为处理程序不知道 handle2() 方法。

为了调用 handle2() 方法(对于有效的 class),您需要将 handler 转换为 ConcreteHandler - 一个已知的过程当您将实例转换为对象层次结构中较低的对象时,就像“向下转换”一样。这仅在 handler 实例实际上是 ConcreteHandler 而不是 Handler.

的其他派生时才有效

示例:

if (handler instanceof ConcreteHandler) {
   ConcreteHandler concreteHandler = (ConcreteHandler) handler;
   concreteHandler.handle2();
}

编辑: 我开始工作的一次性重定向。我不完全确定你如何让它作为文档的永久重定向工作,但如果你想永久重定向该方法,重新定义似乎会起作用。还对制作 classes ConcreteHandler、Handler 等 public.

所需的源代码进行了更改
 new ByteBuddy()
                .subclass(ConcreteHandler.class)
                .method(named("handle")).intercept(MethodDelegation.to(ConcreteHandler.class))
                .make()
                .load(getClass().getClassLoader())
                .getLoaded()
                .newInstance()
                .handle2();

这似乎是字节好友中的一个错误。我希望解决问题 in this commit,这应该可以解决 Byte Buddy 1.10.14 中的问题。您可以同时尝试快照。