为什么在这种情况下,字节好友会将方法委派路由到"wrong"方法?



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

其目的是(同样,非常简单(代理一个类,使其任何非final、非private、非static方法等被路由到其proxiedInstance字段上的等效方法,由其getProxiedInstance方法返回。(对于常见的嫌疑人:equalshashCodewaitnotify等等,应该有例外。(

我已经使用子类策略设置了我的代理类。我还定义了两个方法,getProxiedInstancesetProxiedInstance,以及一个名为proxiedInstance的适当类型的private字段。我使用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"));

在英语中:不是final,不是static,也不是private,并且继承自Object(或重写(的public String toString()方法,未由Object.class声明且未命名为getProxiedInstancesetProxiedInstance的任何其他方法。

假设我有一个这样的类:

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

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

这在某种程度上向我表明,我上面引用的配方是以某种方式将toString()路由到sayHello()

通过阅读MethodDelegationjavadocs,可能会选择目标/委托对象上的sayHello进行委托,因为它比代理上调用的方法(toString(更具体。我想名字匹配的优先级比这个低。

我认为我的这个用例相对简单。我该如何最好地完成它?

我能做的最好的事情是:

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.getMethod("toString")产生的Method。(

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

最新更新