[
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
答案 0 :(得分:106)
可以使用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
答案 1 :(得分:-5)
在这种情况下你可以做的是拥有一个代理处理程序,它将调用重定向到抽象类的现有方法。
你当然必须编写它,但它很简单。要创建代理,您必须给他一个InvocationHandler
。然后,您只需要在调用处理程序的invoke(..)
方法中检查方法类型。但要注意:您必须针对与处理程序关联的基础对象检查方法类型,而不是针对抽象类的声明类型。
如果我以你的狗类为例,你的调用处理程序的调用方法可能看起来像这样(有一个现有的关联狗子类叫做......好...... dog
)< / p>
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.java:362)无法为不代表接口的Class对象创建代理。)
所以,除了现实之外,你想做的事情是完全可能的。