Byte-Buddy:方法拦截 InvocationHandler 与 MethodDelegation to GeneralInterceptor
Byte-Buddy: Method Interception InvocationHandler vs MethodDelegation to GeneralInterceptor
我正在使用 Byte-Buddy 动态生成 Java 接口方法的实现,并将对这些方法的调用委托给现有代理对象的单个方法。
第一个版本的灵感来自
它使用反射 InvocationHandler
即具体代理 class:
- 实现接口
InvocationHandler
- 覆盖方法
invoke()
这很好用。
然后重新阅读 Byte-Buddy readme on Github 我发现了一个使用 MethodDelegation
到 "GeneralInterceptor" 的替代版本。
即具体代理 class:
- 有一个用
RuntimeType
注释标记的方法。
这也很好用!
下面的代码片段展示了这两种技术。
Class<? extends Object> clazz = new ByteBuddy()
.subclass(serviceSuperClass)
.name(className)
// use a Reflection InvocationHander for the methods of serviceInterfaceOne
.implement(serviceInterfaceOne)
.defineField(invocationHandler, MyProxy.class, Visibility.PUBLIC)
.method(isDeclaredBy(serviceInterfaceOne))
.intercept(InvocationHandlerAdapter.toField(invocationHandler))
// use a Byte-Buddy "GeneralInterceptor" for the methods of serviceInterfaceTwo
.implement(serviceInterfaceTwo)
.defineField(generalInterceptor, MyProxy.class, Visibility.PUBLIC)
.method(isDeclaredBy(serviceInterfaceTwo))
.intercept(MethodDelegation.toField(generalInterceptor))
//
.make ()
.load(classLoader)
.getLoaded();
public class MyProxy implements InvocationHandler {
@Override
public Object invoke(Object serviceImpl, Method method, Object[] args) throws Throwable {
return null;
}
@RuntimeType
public Object intercept(@AllArguments Object[] allArguments,
@Origin Method method) {
return null;
}
}
从高层次的角度来看,这两种技术都允许我做同样的事情:
即将给定的动态创建的方法拦截到现有的具体方法。
两种解决方案都很优雅,所需的代码量也差不多。
问题是:有没有理由偏爱其中一个?例如表现?功能?
在这种使用形式中,除了委托可以连接到任何(静态或非静态)方法之外没有真正的区别,而调用处理程序适配器仅桥接 Java 代理的实现API。这主要是指如果您已经实现了这样的代理处理程序并希望在 Byte Buddy 中重用它们。
Byte Buddy 的处理程序比处理程序 API 具有更大的灵活性,这提高了性能,因为如果您知道预期的参数,则可以避免数组装箱。它还允许不同的机制,例如调用调用处理程序 API 不支持的默认方法实现。
我正在使用 Byte-Buddy 动态生成 Java 接口方法的实现,并将对这些方法的调用委托给现有代理对象的单个方法。
第一个版本的灵感来自
它使用反射 InvocationHandler
即具体代理 class:
- 实现接口
InvocationHandler
- 覆盖方法
invoke()
这很好用。
然后重新阅读 Byte-Buddy readme on Github 我发现了一个使用 MethodDelegation
到 "GeneralInterceptor" 的替代版本。
即具体代理 class:
- 有一个用
RuntimeType
注释标记的方法。
这也很好用!
下面的代码片段展示了这两种技术。
Class<? extends Object> clazz = new ByteBuddy()
.subclass(serviceSuperClass)
.name(className)
// use a Reflection InvocationHander for the methods of serviceInterfaceOne
.implement(serviceInterfaceOne)
.defineField(invocationHandler, MyProxy.class, Visibility.PUBLIC)
.method(isDeclaredBy(serviceInterfaceOne))
.intercept(InvocationHandlerAdapter.toField(invocationHandler))
// use a Byte-Buddy "GeneralInterceptor" for the methods of serviceInterfaceTwo
.implement(serviceInterfaceTwo)
.defineField(generalInterceptor, MyProxy.class, Visibility.PUBLIC)
.method(isDeclaredBy(serviceInterfaceTwo))
.intercept(MethodDelegation.toField(generalInterceptor))
//
.make ()
.load(classLoader)
.getLoaded();
public class MyProxy implements InvocationHandler {
@Override
public Object invoke(Object serviceImpl, Method method, Object[] args) throws Throwable {
return null;
}
@RuntimeType
public Object intercept(@AllArguments Object[] allArguments,
@Origin Method method) {
return null;
}
}
从高层次的角度来看,这两种技术都允许我做同样的事情:
即将给定的动态创建的方法拦截到现有的具体方法。
两种解决方案都很优雅,所需的代码量也差不多。
问题是:有没有理由偏爱其中一个?例如表现?功能?
在这种使用形式中,除了委托可以连接到任何(静态或非静态)方法之外没有真正的区别,而调用处理程序适配器仅桥接 Java 代理的实现API。这主要是指如果您已经实现了这样的代理处理程序并希望在 Byte Buddy 中重用它们。
Byte Buddy 的处理程序比处理程序 API 具有更大的灵活性,这提高了性能,因为如果您知道预期的参数,则可以避免数组装箱。它还允许不同的机制,例如调用调用处理程序 API 不支持的默认方法实现。