用于创build抽象类的代理(而不是接口)的java.lang.reflect.Proxy的替代方法

根据文件 :

[ java.lang.reflect. ] Proxy提供了创builddynamic代理类和实例的静态方法,它也是由这些方法创build的所有dynamic代理类的超类。

newProxyMethod方法 (负责生成dynamic代理)具有以下签名:

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

不幸的是,这阻止了生成扩展特定抽象类(而不是实现特定接口)的dynamic代理。 这是有道理的,考虑到java.lang.reflect.Proxy是“所有dynamic代理的超类”,从而防止另一个类成为超类。

因此,是否有可以生成inheritance自特定抽象类的dynamic代理的java.lang.reflect.Proxy替代品,将所有对抽象方法的调用redirect到调用处理程序?

例如,假设我有一个抽象类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 

可以使用Javassist (请参阅ProxyFactory )或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(); 

哪个产生这个输出:

纬!
通过方法处理程序处理公共抽象void mock.Dog.fetch()

在这种情况下你可以做的是有一个代理处理程序,将呼叫redirect到您的抽象类的现有方法。

你当然需要编码,但是很简单。 为了创build你的代理,你必须给他一个InvocationHandler 。 然后,您只需要检查调用处理程序的invoke(..)方法中的方法types。 但是要小心:你必须检查方法types,而不是与你的处理程序关联的底层对象,而不是针对抽象类的声明types。

如果我以你的狗类为例,你的调用处理程序的调用方法可能看起来像这样(与一个现有的相关的狗子类称为…呃… dog

 public void invoke(Object proxy, Method method, Object[] args) { if(!Modifier.isAbstract(method.getModifiers())) { method.invoke(dog, args); // with the correct exception handling } else { // what can we do with abstract methods ? } } 

然而,有些东西让我想知道:我谈到了一个dog 。 但是,由于Dog类是抽象的,你不能创build实例,所以你有现有的子类。 此外,通过对代理源代码的严格检查,您可能会发现(在Proxy.java:362)不可能为不代表接口的Class对象创buildProxy。

所以,除了现实 ,你想要做的是完全可能的。