ジャバシスト:プロキシのプロキシを作成するにはどうすればよいですか?
質問
javassistでプロキシを作成しています ProxyFactory
. 。単一のプロキシを作成する場合は、すべて正常に機能します。
ただし、プロキシされたオブジェクトをプロキシ機構に渡すと、次のエラーが発生して失敗します。
javassist.bytecode.DuplicateMemberException:複製メソッド:com.mypackage.Bean_$$_javassist_0_$$_javassist_1 の setHandler
私はこれでプロキシを作成しています:
public Object createProxiedInstance(Object originalInstance) throws Exception {
Class<?> originalClass = instance.getClass();
ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(originalClass);
factory.setHandler(new MethodHandler() {..});
Class<T> proxyClass = factory.createClass();
return proxyClass.newInstance();
}
では、プロキシのプロキシを作成するにはどうすればよいでしょうか?
アップデート: 実際の問題は、各プロキシが ProxyObject
定義するもの setHandler(..)
方法。したがって、2 番目のプロキシは、サブクラスでメソッドをオーバーライドするのではなく、メソッドを再定義しようとします。
解決
問題だった(実際には、それはCGLIBと同じだ - 私はコモンズ・プロキシを使用して、それを試してみました)私は、プロキシクラスのプロキシクラスを作成しようとはならないこと。第二プロキシは、再び元のクラスでなければなりません。したがって、次の行を追加することで問題を解決します:
if (instance instanceof ProxyObject) {
originalClass = originalClass.getSuperclass();
}
とアドバイス - あなたは(コモンズプロキシで定義されたもののような)インターセプターのいくつかの並べ替えを使用することができた場合、代わりに複数のプロキシを使用するのでそれを行う
。他のヒント
かなり遅い答えですが、それでもこれを知りたいと思うかもしれません:
Javassist プロキシはかなり単純に実装されています。上記のコードでは、Javassist は常に次のメソッドを使用してプロキシ クラスを作成します。
- 基本クラスのオーバーライド可能なメソッドのメソッド
- (a) プロキシ ハンドラーを取得する 2 つの方法 (
getHandler
) および (b) プロキシ ハンドラーを設定します (setHandler
)
後者の 2 つのメソッドの名前は Javassist によってハードコーディングされ、次のように表されます。 ProxyObject
インターフェース。ここでプロキシ クラスのプロキシ クラスを作成すると、Javassist はプロキシ クラスの作成をスケジュールします。 ProxyObject
のメソッドを 2 回実行します。最初の条件で 1 回、2 番目の条件で 1 回。
を設定することでこれを回避できます MethodFilter
これは、 ProxyObject
のメソッドでは、javassist は 2 番目の条件によってのみメソッドを作成します。ただし、これは、もう設定できないことを意味します。 ProxyObject
スーパークラスプロキシの場合、リフレクション経由で対応するフィールドに直接アクセスする必要はありません。したがって、あなたのアプローチはおそらく最もクリーンです。
cglib はインスタンスごとではなくクラスごとにコールバックを定義するため、cglib に関するこの問題は若干異なりますが、別の競合が発生します。
ただし、これらの欠点を抱えないプロキシ クラスを作成したい場合は、私のライブラリに興味があるかもしれません。 バイトバディ これは、特殊なケースで cglib と javassist を使用する作業にイライラした後に書きました。ランタイム コード生成を使用している場合、他のライブラリにはない柔軟性を提供できることを願っています。