4

インターフェイスを実装するクラスを作成せずに、インターフェイスのプロキシを作成するにはどうすればよいですか?

具体的な例があります。Contact インターフェイスがあり、Contact として機能するプロキシ オブジェクトを作成する必要があります。このプロキシ オブジェクトは、一部の TestNG テストの実行に使用されます。

私は JDK アプローチを使用してみましたが、そのインターフェースの実際の実装を必要とする例しか見つけることができませんでした。

また、jassist がこの問題に役立つ可能性があることもわかり、メモリ不足エラーが発生するまで機能しているように見える簡単な例を実装しようとしました。ここに私がやっていることのスニペットがあります:

import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory

protected final T createMock(final Class<T> clazz) {
    final ProxyFactory factory = new ProxyFactory();
    factory.setInterfaces(new Class[] { clazz });
    factory.setFilter(new MethodFilter() {
        public final boolean isHandled(final Method m) {
            // ignore finalize()
            return !m.getName().equals("finalize");
        }
    });

    final MethodHandler handler = createDefaultMethodHandler();
    try {
        return (T) factory.create(new Class<?>[0], new Object[0], handler);
    } catch (final Exception e) {
        e.printStackTrace();
    }
    return null;
}
private MethodHandler createDefaultMethodHandler() {
    return new MethodHandler() {
        public final Object invoke(final Object self,
                final Method thisMethod, final Method proceed,
                final Object[] args) throws Throwable {
            System.out.println("Handling " + thisMethod
                    + " via the method handler");
            return thisMethod.invoke(self, args);
        }
    };
}

createMock() メソッドのパラメーターはインターフェースになることに注意してください。

ありがとう

4

5 に答える 5

8

newProxyInstanceの方法が使えますjava.lang.reflect.Proxy。元:

    Proxy.newProxyInstance(iClazz.getClassLoader(),
        new Class[]{iClazz},
        new YourInvocationHandler())

iClazzインターフェイスのクラスでありYourInvocationHandler、のインスタンスですjava.lang.reflect.InvocationHandler

于 2012-09-19T16:40:44.403 に答える
2

commons-proxyは、タスクを簡素化することを目的としています。

必要なのは、呼び出し側プロキシ (ターゲット オブジェクトなし) です。したがって、次を使用できます。

ProxyFactory factory = new JavassistProxyFactory();
Object result = 
      factory.createInvokerProxy(invoker, new Class[] {YourInterface.class});

そして、各メソッド呼び出しでメソッドが呼び出されるインターフェイスをinvoker実装する必要があります。(ここでは "invoke" の 4 回)Invokerinvoke

commons-proxy は、推奨される基本的なプロキシ メカニズムを使用することに注意してください。上記の例では、それは javassist です。


ただし、モックの目的でプロキシが必要なようです。これは、 mockitoを使用すると次のように簡単です。

YourInterface yourMock = mock(YourInterface.class);
when(yourMock.someMethod()).thenReturn(yourPreferredResult);
于 2010-10-05T10:12:31.303 に答える
1

モッキングだけに興味がある場合は、フレームワークを使用することをお勧めします。

EasyMock ( http://easymock.org/ ) または JMock ( http://www.jmock.org/ ) が適合する可能性があります。

自分でプロキシを作成するには、クラスを使用できますjava.lang.reflect.Proxy

于 2010-10-05T10:11:29.700 に答える
0

あなたのコードで私は次のことをしました

//              return thisMethod.invoke(self, args);
            return null;

そして、私は次の結果を得ました

Handling public abstract void org.rege.instruments.IPerson.setName(java.lang.String) via the method handler

これはあなたが望んでいたものですか?ご覧のとおり、OutOfMemory は呼び出しへの再帰呼び出しによって生成されました。

于 2010-10-31T21:27:02.867 に答える
0

java.lang.reflect.proxyExampledepot には、http://exampledepot.8waytrips.com/egs/java.lang.reflect/ProxyClass.htmlに基づいてインターフェイス プロキシを作成する方法の簡単なスニペットがあります。

invoke(Object proxy, Method m, Object[] args)独自のコードでの機能を提供する必要があるだけです。


編集: コメントに基づいて、不要なクラスは実装クラスではなくインターフェイスクラスのようです。その場合、バイトコード操作を回避する方法はありません。スニペット コンパイラを含む Javassist を参照してください。

于 2010-10-05T10:40:14.717 に答える