1

最近、プロキシオブジェクトを扱っていると、難しい質問にたどり着きました...それを共有し、あなたの意見を聞きたいです...おそらく、解決策...質問が有効であることが証明された場合。

動的プロキシを使用して、作業をclassを実装する別のものに委譲しInvocationHandler interface、invoke メソッドを上書きすることで、ターゲット オブジェクトで呼び出された任意のメソッドをインターセプトできます。これにより、動作を追加し、後でターゲット オブジェクトに委譲する可能性が与えられます (おそらく実または他のプロキシ) リフレクションを使用します。プロキシしたいオブジェクトを持つ a が実装されている必要がありますinterfaceconcrete classそのため、インターフェイスを操作します。

問題は、プロキシオブジェクトでは最初に呼び出されたメソッドのみがインターセプトされるためだと思います...つまり、concreteオブジェクトのメソッド内(インターフェースではなくクラスが具象であるオブジェクト)の場合、他のインスタンスメソッドへの呼び出しがあります、これらのメソッドはconcrete、プロキシ経由ではなく、オブジェクトによって直接呼び出されます(呼び出しハンドラーを再度考えて渡す前に)。interface「動的プロキシ」のクラスは のサブクラスと見なされますが、クラスのサブクラスとは見なされないことを知っていconcreteます..クラス内ではconcrete、プロキシオブジェクトクラスがサブタイプでない限り、「this」キーワードはプロキシオブジェクトを参照できませんof concrete..、実際には「動的プロキシ」のクラスのconcreteための「兄弟」ですconcreteinterface.

見てください。次のシナリオをコードに入れてください。かなり問題のある状況が見つかりました。

public class Example
{

    static interface OutputerInterface
    {
        String getText();

        void out();

        void setText(String data);

    }

    static class Outputer implements OutputerInterface {

        private String txt;

        public Outputer()
        {
            this.txt = null;
        }

        @Override
        public String getText()
        {
            return txt;
        }

        @Override
        public void setText(String data)
        {
            this.txt = data;
        }

        @Override
        public void out () {
            String text = this.getText();
            System.out.println (text);
        }
    }

    static class OutputerInvocationHandler implements InvocationHandler {
        private OutputerInterface outputer;

        public OutputerInvocationHandler(OutputerInterface concreteEntity)
        {
            this.outputer = concreteEntity;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
        {
            String methodName = method.getName();
            System.out.println("Intercepted " + methodName);
            if (methodName.equals("getText"))
            {
                if (this.outputer.getText() == null) { // only if not setted
                    this.outputer.setText("Hi, i am outputer");
                }
            }

            return method.invoke(outputer, args);
        }
    }

    static OutputerInterface proxify (OutputerInterface entity) {
        return (OutputerInterface) Proxy.newProxyInstance(
                Outputer.class.getClassLoader(),
                Outputer.class.getInterfaces(), 
                new OutputerInvocationHandler(entity));
    }


    public static void main(String[] args)
    {
        OutputerInterface outputer;

        outputer = proxify (new Outputer());
        String text = outputer.getText(); 
        System.out.println (text); // this works!

        outputer = proxify (new Outputer());
        outputer.out(); // this doesn´t works
    }
}

getText() がプロキシから直接呼び出されたかどうかにかかわらず、確実に傍受されるようにする方法はありますか。ありがとう!ご挨拶!ビクター。

4

2 に答える 2

1

これは、Java の組み込みの動的プロキシの制限です。実装できるインターフェイスの数は限られていますが、クラスを拡張することはできません。

あなたの場合、あなたがやろうとしているのは拡張Outputerであり、いいえ、設計上、動的プロキシではそれを行うことはできません。代わりに、 CGLibなどのランタイム コード生成ライブラリを試す必要があります。

于 2013-10-02T16:46:49.940 に答える