用于创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。
所以,除了现实 ,你想要做的是完全可能的。