【问题标题】:Method delegation on field and cast in Bytebuddy现场方法委托并在 Bytebuddy 中投射
【发布时间】:2020-07-12 05:42:25
【问题描述】:

使用 Bytebuddy 假设如下:

class Service {
    protected Handler handler;
...
}

interface Handler {
   public void handle();
}

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

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

我试过了:

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

...但它失败并出现 IllegalStateException: Cannot invoke public void com.framework.ConcreteHandler.handle2(...) on protected com.framework.Handler com.framework.Service.handler

有什么想法吗?

【问题讨论】:

    标签: java byte-buddy


    【解决方案1】:

    这似乎是 Byte Buddy 中的一个错误。我希望解决了in this commit 的问题,这应该可以解决 Byte Buddy 1.10.14 中的问题。您可以在此期间尝试快照。

    【讨论】:

    • 感谢您的努力。内部的 isInvokableOn() 是什么?一般来说听起来很合适...
    • 它检查一个方法是否可以在给定类型上调用,而子类型方法是否在它的超类型上是不可调用的。因此,该检查不适用,因为它没有考虑强制转换。
    • 明白。在提交中,您削弱了检查以便进行强制转换,对吗?
    • 是的。就是这样。
    • 我可以确认 (a) 这个一般问题是 ByteBuddy 中的一个问题,并且 (b) 1.10.14-SNAPSHOT(从 2020-07-16 的源代码构建)修复了它。谢谢@RafaelWinterhalter 的快速修复。
    【解决方案2】:

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

    为了调用 handle2() 方法(对于有效类),您需要将 handler 转换为 ConcreteHandler - 当您将实例转换为时,该过程称为“向下转换”对象层次结构中较低的对象。这仅在 handler 实例实际上是 ConcreteHandler 而不是 Handler 的其他派生时才有效。

    示例:

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

    编辑: 我开始工作的一次性重定向。我不完全确定您如何将其作为文档中的永久重定向工作,但如果您想永久重定向该方法,重新定义似乎会起作用。为了使 ConcreteHandler、Handler 等类公开所需的源代码也进行了更改。

     new ByteBuddy()
                    .subclass(ConcreteHandler.class)
                    .method(named("handle")).intercept(MethodDelegation.to(ConcreteHandler.class))
                    .make()
                    .load(getClass().getClassLoader())
                    .getLoaded()
                    .newInstance()
                    .handle2();
    

    【讨论】:

    • 感谢您的回答,但这个问题是在使用 ByteBuddy 的背景下进行的。此演员表必须以 Bytebuddy 的描述语言进行......
    • 啊,我的错!您是否尝试过这里的委托示例:baeldung.com/byte-buddy - 我要试一试。如果我有运气,我会回来的
    • 我尝试了这一点,并设法重定向了呼叫,但只是一次性的,而不是永久的。我看到作者已经给出了答案。这是一个有趣的项目,我以前没有遇到过,所以谢谢你的问题:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 2019-08-17
    相关资源
    最近更新 更多