web-dev-qa-db-fra.com

Alternatives à Java.lang.reflect.Proxy pour créer des proxys de classes abstraites (plutôt que des interfaces)

Selon la documentation :

[Java.lang.reflect.] Proxy fournit des méthodes statiques pour créer des classes et des instances de proxy dynamiques, et c'est également la superclasse de toutes les classes de proxy dynamiques créées par ces méthodes.

La méthode newProxyMethod (responsable de la génération des proxys dynamiques) a la signature suivante:

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

Malheureusement, cela empêche de générer un proxy dynamique qui étend une classe abstraite spécifique (plutôt que implémentant des interfaces spécifiques). Cela a du sens, compte tenu de Java.lang.reflect.Proxy est "la superclasse de tous les proxys dynamiques", empêchant ainsi une autre classe d'être la superclasse.

Par conséquent, existe-t-il des alternatives à Java.lang.reflect.Proxy qui peut générer des proxys dynamiques qui héritent à partir d'une classe abstraite spécifique, redirigeant tous les appels vers les méthodes abstract ​​vers le gestionnaire d'invocation?

Par exemple, supposons que j'ai une classe abstraite Dog:

public abstract class Dog {

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

    public abstract void fetch();

}

Y a-t-il une classe qui me permet de faire ce qui suit?

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

Cela peut être fait en utilisant Javassist (voir ProxyFactory ) ou CGLIB .

Exemple d'Adam utilisant Javassist:

J'ai (Adam Paynter) écrit ce code en utilisant 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();

Ce qui produit cette sortie:

 Woof! 
 Gestion du résumé public void mock.Dog.fetch () via le gestionnaire de méthode 
107
axtavt