Javaでは、InvocationHandler
の実装を使用して動的プロキシを作成することができます。 JVMの最適化にもかかわらず、リフレクションの使用には常にメソッドを呼び出すオーバーヘッドがあります。ByteBuddyを使用して動的プロキシを作成する方法
この問題を解決しようとすると、実行時にByteBuddyを使用してプロキシクラスを作成しようとしましたが、ドキュメントがこの面で十分にはっきりしていないようです。
メソッドの呼び出しをいくつかのクラスインスタンスに転送するために、MethodCallProxy
を作成するにはどうすればよいですか?
編集:私はRPCシステムを構築してい
:
より良い私の問題を明確にするためには、私は私が達成したいものの例を提供しています。メソッド呼び出しの各側で、私は、(両方の呼び出し元/呼び出し先がJVMの下で実行されている)契約を定義するインタフェースを持っています。
@Contract
interface ISomeService {
fun someMethod(arg0: String, arg1: SomePojo): PojoResult
}
コールサイトでは、すべてのメソッド呼び出しをインターセプトして呼び出し先に転送するプロキシを挿入します。
ByteBuddy()
.subclass(Any::class.java)
.implement(serviceClass)
// Service contract method delegation
.method(isDeclaredBy(serviceClass)).intercept(
MethodDelegation
.to(ServiceProxyInterceptor())
.filter(not(isDeclaredBy(Any::class.java)))
)
.make()
.load(this)
.loaded as Class<T>
そして、最後に、呼び出し先で、私は、呼び出しパラメーターを非整列化し、サービスの実装に転送するための責任、いくつかのハンドラ、各サービスのメソッドのいずれかを持っています。
@Service
class SomeServiceImpl {
fun someMethod(arg0: String, arg1: SomePojo): PojoResult {
// ...
}
}
私は、コード生成を使用してこの問題を解決することができますが、結果としてjar
ファイルが非常に大きくなることができます。したがって、これらのハンドラの汎用バージョンを作成し、それぞれのメソッド呼び出しをすべてのメソッド呼び出しを傍受してISomeService
に接続し、SomeServiceImpl
に転送する必要があります。
もちろん、この質問の特定の部分に対処するために、InvokeHandlerを呼び出すByteBuddy生成プロキシがJREが 'java.lang.reflect.Proxy'を生成したより効率的であると仮定する理由はありません。 InvocationHandler' ... – Holger
違いは主にJVMがインターフェイスのみをサポートしているのに対して、Byte Buddyは計測器クラスもサポートしている点です。パフォーマンス面では、リフレクションに比べてコード生成のメリットがあると思います。後者は疑わしいです。ほとんどの場合、私はリフレクション・インフレーションが十分であると思っています。 –
私はByteBuddyとReflectionの機能の違いを知っていますが、問題はこれがまったく問題ではないことを示しています。唯一言及された動機はReflectionの主張されたオーバーヘッドです。パフォーマンスが重要なシナリオがあるかもしれませんが、 'InvocationHandler'に固執すると、コード生成は間違った終わりに対処しています。たとえば、プリミティブ型のボクシングと引数を配列に埋め込むことは... – Holger