用于创建抽象类(而不是接口)代理的 java.lang.reflect.Proxy 的替代方案
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3291637/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Alternatives to java.lang.reflect.Proxy for creating proxies of abstract classes (rather than interfaces)
提问by Adam Paynter
According to the documentation:
根据文档:
[
java.lang.reflect.
]Proxy
provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.
[
java.lang.reflect.
]Proxy
提供了用于创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
The newProxyMethod
method(responsible for generating the dynamic proxies) has the following signature:
该newProxyMethod
方法(负责生成动态代理)具有以下签名:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
Unfortunately, this prevents one from generating a dynamic proxy that extendsa specific abstract class (rather than implementingspecific interfaces). This makes sense, considering java.lang.reflect.Proxy
is "the superclass of all dynamic proxies", thereby preventing another class from being the superclass.
不幸的是,这阻止了生成扩展特定抽象类(而不是实现特定接口)的动态代理。这是有道理的,考虑到java.lang.reflect.Proxy
“所有动态代理的超类”,从而防止另一个类成为超类。
Therefore, are there any alternatives to java.lang.reflect.Proxy
that can generate dynamic proxies that inheritfrom a specific abstract class, redirecting all calls to the abstractmethods to the invocation handler?
因此,是否有任何替代方法java.lang.reflect.Proxy
可以生成从特定抽象类继承的动态代理,将所有对抽象方法的调用重定向到调用处理程序?
For example, suppose I have an abstract class Dog
:
例如,假设我有一个抽象类Dog
:
public abstract class Dog {
public void bark() {
System.out.println("Woof!");
}
public abstract void fetch();
}
Is there a class that allows me to do the following?
是否有一个课程允许我执行以下操作?
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
采纳答案by axtavt
It can be done using Javassist(see ProxyFactory
) or CGLIB.
可以使用Javassist(请参阅参考资料ProxyFactory
)或CGLIB来完成。
Adam's example using Javassist:
Adam 使用 Javassist 的示例:
I (Adam Paynter) wrote this code using 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();
Which produces this output:
产生这个输出:
Woof! Handling public abstract void mock.Dog.fetch() via the method handler
回答by Riduidel
What you can do in such a case is having a proxy handler that will redirect calls to existing methods of your abstract class.
在这种情况下,您可以做的是拥有一个代理处理程序,它将调用重定向到您的抽象类的现有方法。
You of course will have to code it, however it's quite simple. For creating your Proxy, you'll have to give him an InvocationHandler
. You'll then only have to check the method type in the invoke(..)
method of your invocation handler. But beware : you'll have to check the method type against the underlying object associated to your handler, and not against the declared type of your abstract class.
您当然必须对其进行编码,但这非常简单。为了创建你的代理,你必须给他一个InvocationHandler
. 然后,您只需在invoke(..)
调用处理程序的方法中检查方法类型。但要注意:您必须根据与处理程序关联的底层对象检查方法类型,而不是根据抽象类的声明类型。
If I take as an example your dog class, your invocation handler's invoke method maylook like this (with an existing associated dog subclass called .. well ... dog
)
如果我以您的狗类为例,则您的调用处理程序的 invoke 方法可能如下所示(具有名为 .. 的现有关联狗子类... 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 ?
}
}
However, there is something that keep me wondering : I've talked about a dog
object. But, as the Dog class is abstract, you can't create instances, so you have existing subclasses. Furthermore, as a rigorous inspection of Proxy source code reveals, you may discover (at Proxy.java:362) that it is not possible to create a Proxy for a Class object that does not represents an interface).
然而,有一点让我感到疑惑:我谈到了一个dog
对象。但是,由于 Dog 类是抽象的,您无法创建实例,因此您有现有的子类。此外,正如对 Proxy 源代码的严格检查所揭示的那样,您可能会发现(在 Proxy.java:362 中)无法为不代表接口的 Class 对象创建代理)。
So, apart from the reality, what you want to do is perfectly possible.
所以,抛开现实,你想做的事完全有可能。