当前位置: 首页 > 知识库问答 >
问题:

在这种情况下,为什么ByteBuddy会将方法委托给“错误”的方法?

燕刚捷
2023-03-14

我正在创建一个非常简单的ByteBuddy委托/代理类。

其意图(同样非常简单)是代理一个类,这样它的任何非最终、非私有、非静态方法等都会被路由到它的proxiedInstance字段上的等效方法,正如它的getProxiedInstance方法返回的那样。(通常的嫌疑犯应该有例外:等于哈希码等待通知等等。)

我使用子类策略设置了我的代理类。我还定义了两个方法,getProxiedInstancesetProxiedInstance,以及一个名为proxiedInstance的适当类型的私有字段。我使用FieldAccessor.ofBeanProperty()策略完成了这一点。为了简洁明了,我在这里省略了它。该类实际上包含这个字段和这两个方法。

然后我像这样定义了方法拦截,静态导入相关的ElementMatchers方法:

builder
      .method(not(isFinal()).and(not(isStatic())).and(not(isPrivate()))
              .and((isPublic().and(named("toString")).and(takesArguments(0)).and(returns(String.class)))
                   .or((not(isDeclaredBy(Object.class)).and(not(named("getProxiedInstance"))).and(not(named("setProxiedInstance"))))))
              )
      .intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"));

英文:notfinal、notstatic、notprivate、以及从对象继承的公共字符串toString()方法(或重写的方法),或对象未声明的任何其他方法。类且未命名getProxiedInstancesetProxiedInstance

假设我有一个这样的类:

public class Frob {

  public String sayHello() {
    return "Hello!";
  }

}

当我为它创建一个代理类,实例化它,然后在代理上调用toString()时,我得到Hello!

这在某种程度上向我暗示,我上面引用的菜谱是以某种方式将toString()路由到sayHello()

从阅读MESTODENATIONjavadocs中,似乎可能会选择目标/委托对象上的sayHello进行委托,因为它比在代理上调用的方法更具体(toString)。我猜名称匹配的优先级低于此。

我认为我的这个用例相对简单。我怎样才能最好地完成它?


共有2个答案

微生德运
2023-03-14

我认为使用MethodCall是一种更好的方法MethodDelegation用于“捕获所有代理”,您可以将相应的分派器注入到通常是单个委派方法(可能是两个)中。方法调用的性能也要高得多,因为它不需要进行分析,只需要重新路由到兼容类型的方法。

常业
2023-03-14

我能做的最好的事情是这样的,虽然效果不错,但似乎有点笨拙或冗长:

builder = builder
      .method(not(isDeclaredBy(Object.class))
              .and(not(isFinal()))
              .and(not(isStatic()))
              .and(not(isPrivate()))
              .and(not(named("getProxiedInstance")))
              .and(not(named("setProxiedInstance"))))
      .intercept(MethodDelegation.toMethodReturnOf("getProxiedInstance"))
      .method(is(toStringMethod))
      .intercept(invoke(toStringMethod).onMethodCall(invoke(named("getProxiedInstance"))));

toStringMethod是由Object.class.get方法("toString")产生的方法。)

 类似资料:
  • 输入是:1。硬币中一定数量货币的总重量,2。旧货币硬币的价值和相应重量。 目标是找到给定金额货币的最低可能货币价值。 我的方法是按货币的价值/重量比升序对硬币进行排序,然后贪婪地将第一枚硬币的重量尽可能多地匹配到总和中(跟踪它匹配的次数),然后匹配将第二枚硬币的重量尽可能多次地放入余数中,等等,对于所有硬币或直到余数为零(如果不是,情况是不可能的)。 法官说我的答案是错误的。你能给我一个关于算法错

  • 根据Java教程 将包装类型(整数)的对象转换为其相应的基元(int)值称为取消装箱。当包装类的对象为: 作为参数传递给需要相应基元类型的值的方法 分配给相应基元类型的变量 为什么在这种情况下会发生拆箱? 在这种情况下,这些事情发生在哪里?是否有管理数组中元素访问的底层方法?或者[]暗示某种变量?

  • 问题内容: 我编写了以下代码来实现Singleton模式: 当我编译此文件时,它应该生成Test.class和Test $ TestHolder.class,但它还会生成Test $ 1.class。这没有道理。那么,为什么以及如何呢? 问题答案: 类需要在中调用私有构造函数。但是它是私有的,实际上不能从另一个类中调用。因此,编译器发挥了作用。它 添加了一个仅知道的新的非私有构造函数!_该构造函数

  • 问题内容: 我有两个例子: 范例1: 范例2: 在 第二个 例子不工作,我想它做的事。我的意思是文件内容不为空,但好像zip文件已损坏。 我想告诉我第一个例子为什么不起作用。 问题答案: 必须在流的末尾执行多项操作以完成zip文件,因此必须正确关闭它。(一般来讲,按照惯例,每个流几乎都 应该 正确关闭。)

  • 问题内容: 我有一个父类A,及其子B。两者都具有带有diff类型参数的方法。 A级 B级 运行此命令时,将获得“ Base impl:override”作为输出! 指向的对象,而他经过的说法是,所以不应该调用它的方法是什么? 问题答案: 当您使用类型A的引用时,您只会看到为类A定义的方法。由于B中不会覆盖B(因为它具有不同的签名),因此不会调用它。 如果要使用类型B的引用,则两种方法都将可用,并且

  • 安装问题 PS C:\Users\Administrator sharp@0.21.3安装C:\用户\管理员\gatsby-site3\node_modules\锐(节点安装/libvips 使用缓存的C:\Users\Administrator\AppData\Roaming\npm-cache\u libvips\libvips-8.7.0-win32-x64.tar.gz info shar