[java.lang.reflect.]Proxy 提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
newProxyMethod
method(负责生成动态代理)具有以下签名:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
不幸的是,这阻止了生成一个扩展特定抽象类(而不是实现特定接口)的动态代理。这是有道理的,考虑到 java.lang.reflect.Proxy
是“所有动态代理的超类”,从而防止另一个类成为超类。
因此,是否有任何替代 java.lang.reflect.Proxy
可以生成从特定抽象类继承的动态代理,将对 abstract 方法的所有调用重定向到调用处理程序?
例如,假设我有一个抽象类 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 来完成。
Adam 使用 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! Handling public abstract void mock.Dog.fetch() via the method handler
在这种情况下,您可以做的是拥有一个代理处理程序,它将调用重定向到抽象类的现有方法。
您当然必须对其进行编码,但这很简单。为了创建您的代理,您必须给他一个 InvocationHandler
。然后,您只需检查调用处理程序的 invoke(..)
方法中的方法类型。但请注意:您必须对照与处理程序关联的底层对象检查方法类型,而不是对照抽象类的声明类型。
如果我以您的 dog 类为例,您的调用处理程序的调用方法可能如下所示(现有关联的 dog 子类称为 ..well ... 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 类是抽象的,您不能创建实例,因此您有现有的子类。此外,正如对 Proxy 源代码的严格检查所揭示的那样,您可能会发现(在 Proxy.java:362 处)不可能为不代表接口的 Class 对象创建代理)。
所以,抛开现实,你想做的事是完全可能的。
Dog
的子类(例如,我m 未明确编写实现 fetch()
的 Poodle
类)。因此,没有 dog
变量可以调用这些方法......对不起,如果我感到困惑,我将不得不再考虑一下。
java.lang.reflect.Proxy
以外的东西)可以满足我的需要。
proxyFactory.setHandler()
已弃用。请使用proxy.setHandler
。