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
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