web-dev-qa-db-ja.com

(インターフェースではなく)抽象クラスのプロキシを作成するためのJava.lang.reflect.Proxyの代替

ドキュメント によると:

[_Java.lang.reflect._] Proxyは、動的プロキシクラスおよびインスタンスを作成するための静的メソッドを提供し、それらのメソッドによって作成されるすべての動的プロキシクラスのスーパークラスでもあります。

newProxyMethod method (動的プロキシの生成を担当)には次のシグネチャがあります。

_public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
                             throws IllegalArgumentException
_

残念ながら、これにより、特定の抽象クラスをextendsimplementing特定のインターフェースではなく)動的プロキシを生成できません。 _Java.lang.reflect.Proxy_は「すべての動的プロキシのスーパークラス」であり、別のクラスがスーパークラスになるのを防ぐため、これは理にかなっています。

したがって、特定の抽象クラスからinheritを動的プロキシを生成し、すべての呼び出しをabstractにリダイレクトできる_Java.lang.reflect.Proxy_に代わるものはありますか呼び出しハンドラへのメソッド?

たとえば、抽象クラスDogがあるとします。

_public abstract class Dog {

    public void bark() {
        System.out.println("Woof!");
    }

    public abstract void fetch();

}
_

次のことができるクラスはありますか?

_Dog dog = SomeOtherProxy.newProxyInstance(classLoader, Dog.class, h);

dog.fetch(); // Will be handled by the invocation handler
dog.bark();  // Will NOT be handled by the invocation handler
_
77
Adam Paynter

JavassistProxyFactory を参照)または [〜#〜] cglib [〜#〜] を使用して実行できます。

Javassistを使用したアダムの例:

私(Adam Paynter)は、Javassistを使用してこのコードを作成しました。

ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Dog.class);
factory.setFilter(
    new MethodFilter() {
        @Override
        public boolean isHandled(Method method) {
            return Modifier.isAbstract(method.getModifiers());
        }
    }
);

MethodHandler handler = new MethodHandler() {
    @Override
    public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
        System.out.println("Handling " + thisMethod + " via the method handler");
        return null;
    }
};

Dog dog = (Dog) factory.create(new Class<?>[0], new Object[0], handler);
dog.bark();
dog.fetch();

次の出力が生成されます:

 Woof!
 public抽象void mock.Dog.fetch()をメソッドハンドラーで処理する
107
axtavt