我正在创建一个非常简单的ByteBuddy委托/代理类。
其目的是(同样,非常简单(代理一个类,使其任何非final
、非private
、非static
方法等被路由到其proxiedInstance
字段上的等效方法,由其getProxiedInstance
方法返回。(对于常见的嫌疑人:equals
、hashCode
、wait
和notify
等等,应该有例外。(
我已经使用子类策略设置了我的代理类。我还定义了两个方法,getProxiedInstance
和setProxiedInstance
,以及一个名为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
声明且未命名为getProxiedInstance
或setProxiedInstance
的任何其他方法。
假设我有一个这样的类:
public class Frob {
public String sayHello() {
return "Hello!";
}
}
当我为它创建一个代理类,实例化它,然后在代理上调用toString()
时,我得到了Hello!
。
这在某种程度上向我表明,我上面引用的配方是以某种方式将toString()
路由到sayHello()
。
通过阅读MethodDelegation
javadocs,可能会选择目标/委托对象上的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
用于"捕获所有代理",在这里您可以将相应的调度器注入到通常是单个委托方法,可能是两个。方法调用的性能也高得多,因为它不需要进行分析,只需要重新路由到兼容类型的方法。