9

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がwhichdefinesetHandler(..)メソッドを実装していることです。したがって、2番目のプロキシは、サブクラスでメソッドをオーバーライドするのではなく、メソッドを再定義しようとしています。

4

2 に答える 2

4

問題は(実際には、CGLIBと同じです-commons-proxyを使用して試しました)、プロキシクラスのプロキシクラスを作成しようとすべきではないということでした。2番目のプロキシも元のクラスである必要があります。したがって、次の行を追加すると問題が解決します。

if (instance instanceof ProxyObject) {
    originalClass = originalClass.getSuperclass();
}

そしてアドバイス-ある種のインターセプター(commons-proxyで定義されているものなど)を使用できる場合は、複数のプロキシを使用する代わりにそれを実行してください。

于 2010-04-12T21:19:59.337 に答える
1

それはかなり遅い答えですが、あなたはまだこれを知ることに興味があるかもしれません:

Javassistプロキシはかなり素朴に実装されています。上記のコードでは、Javassistは常に次のメソッドを使用してプロキシクラスを作成します。

  1. 基本クラスのオーバーライド可能なメソッドのメソッド
  2. getHandler(a)プロキシハンドラーを取得する( )と(b)プロキシハンドラーを設定する()setHandlerの2つの方法

後者の2つのメソッドの名前は、Javassistによってハードコーディングされ、インターフェースによって表されProxyObjectます。ここでプロキシクラスのプロキシクラスを作成すると、JavassistはのProxyObjectメソッドの作成を2回スケジュールします。最初の条件で1回、2番目の条件で1回。

javassistが2番目の条件でのみメソッドを作成するように、のメソッドをMethodFilterオーバーライドしないように指定するaを設定することで、これを回避できます。ただし、これは、リフレクションを介して対応するフィールドに直接アクセスせずに、スーパークラスプロキシのをProxyObject設定できなくなったことを意味します。ProxyObjectしたがって、あなたのアプローチはおそらく最もクリーンです。

cglibは、インスタンスごとではなくクラスごとにコールバックを定義するため、cglibのこの問題はわずかに異なりますが、別の競合が発生します。

ただし、これらの欠点に悩まされないプロキシクラスを作成したい場合は、コーナーケースで作業するときにcglibとjavassistで作業することに不満を感じた後、私が作成したライブラリByteBuddyに興味があるかもしれません。ランタイムコード生成を使用している場合は、他のライブラリにはない柔軟性が提供されることを願っています。

于 2014-05-03T14:33:35.837 に答える