2

クラス内の特定のメソッドを処理する際の仲介者となるように動的プロキシを作成しました。これは、制御する必要がある各インターフェイスのすべてのメソッドをオーバーライドする必要がないようにするためです。

ワッフリーは、誰も理解したり気にしたりしないだろうと言っています(ただし、質問にさらにコンテキストを追加する可能性があります):

これから紹介する例では、コンパイルして自分でテストおよび実行できるように、汎用的にしようとしましたが、実際の状況では、次のようなものがあります。

interface CommandSender

interface ConsoleCommandSender extends CommandSender
interface Player extends CommandSender

インスタンスのプロキシを作成するConsoleCommandSender場合、結果のプロキシはCommandSender. 実際には、ConsoleCommandSenderすべてのインターフェースをリストしていないため、次のgetInterfaces()ことが起こります。

java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender

Player クラスにはこの問題はなく、常に にキャスト可能CommandSenderです。

本当の質問:

したがって、次のコードを出発点として使用すると、 で示されるプロキシmyProxyを、ClassCastException.

次のコードは正常にコンパイルおよび実行されますがList、. ではなくArrayList.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

public class ProxyClass implements InvocationHandler {

    private Object classProxy;

    public static void main(String[] args) {
        // Example declaration
        // (I know the proxy should really be cast as an ArrayList
        // but this is my point, it SHOULD work anyway)
        ArrayList methodObject = new ArrayList<String>();
        List<String> myProxy = (List<String>)ProxyClass.newInstance(methodObject, false);

        // Example usage
        myProxy.add("Hello World!");
        System.out.println(myProxy.get(0));
    }

    public static Object newInstance(Object proxy, boolean silent) {
        return Proxy.newProxyInstance(
                proxy.getClass().getClassLoader(),
                proxy.getClass().getInterfaces(),
                new ProxyClass(proxy));
    }

    private ProxyClass(Object proxy) {
        this.classProxy = proxy;
    }

    // Is called whenever a method is invoked
    public Object invoke(Object p, Method m, Object[] args) throws Throwable {
        return m.invoke(classProxy, args);
    }

}

<T>この問題の予備的な部分について私が作成した別のスレッドで、ある人が、変数を使用して別の有効なインターフェイスをリストに追加できるとコメントしました。これを実装する方法はよくわかりませんでしたが、良いスタートのように思えました。

4

1 に答える 1

0

私はあなたの質問を理解したと認めることを100%確信していません.ArrayListに「直接」キャストできるようにしたいですか?つまり -

    ArrayList<String> myProxy = (ArrayList<String>)ProxyClass.newInstance(methodObject, false);

これはあなたにはうまくいきません。その理由は、生成されたオブジェクトが ArrayList のインスタンスではないためです。ある意味では、動作はデコレータに似ています。
デコレータはそれが装飾するオブジェクトのインスタンスですか? いいえ、同じインターフェースに準拠しています。
あなたがすべきことは、CGLIBの使用を検討することです。CGLIB を使用すると、クラスのプロキシ (傍受されたオブジェクト) を作成できます。
CGBLib によってプロキシされたオブジェクトは、実際にはプロキシされたオブジェクトのインスタンスです。私の記憶が正しければ、Hibernate はエンティティ オブジェクトをプロキシする
ために CGLib と ASM を使用し
ます。

于 2012-10-12T15:36:49.160 に答える