java 如何在Java中创建接口的代理?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3862525/
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
How to create a proxy of an interface in Java?
提问by virgium03
How can one create a proxy for an interface without creating a class that implements it?
如何在不创建实现它的类的情况下为接口创建代理?
I have a concrete example: I have an interface, Contact, and need to create a proxy object that acts as a Contact. This proxy object will be used for running some TestNG tests.
我有一个具体的例子:我有一个接口,Contact,需要创建一个充当 Contact 的代理对象。此代理对象将用于运行一些 TestNG 测试。
I have tried using the JDK approach but could find only examples that needed an actual implementation of that interface.
我曾尝试使用 JDK 方法,但只能找到需要实际实现该接口的示例。
I also found that jasssist may help me in this problem and tried implementing a simple example that seems to be working until I get an Out of Memory error. Here is a snippet of what I am doing:
我还发现 jassist 可以帮助我解决这个问题,并尝试实现一个简单的示例,该示例似乎可以正常工作,直到出现内存不足错误。这是我正在做的一个片段:
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.ProxyFactory
protected final T createMock(final Class<T> clazz) {
final ProxyFactory factory = new ProxyFactory();
factory.setInterfaces(new Class[] { clazz });
factory.setFilter(new MethodFilter() {
public final boolean isHandled(final Method m) {
// ignore finalize()
return !m.getName().equals("finalize");
}
});
final MethodHandler handler = createDefaultMethodHandler();
try {
return (T) factory.create(new Class<?>[0], new Object[0], handler);
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
private MethodHandler createDefaultMethodHandler() {
return new MethodHandler() {
public final Object invoke(final Object self,
final Method thisMethod, final Method proceed,
final Object[] args) throws Throwable {
System.out.println("Handling " + thisMethod
+ " via the method handler");
return thisMethod.invoke(self, args);
}
};
}
Remember that the parameter of the createMock() method will be an interface.
请记住, createMock() 方法的参数将是一个接口。
Thanks
谢谢
回答by Bateramos
You can use the method newProxyInstance
of java.lang.reflect.Proxy
.
Ex:
您可以使用该方法newProxyInstance
的java.lang.reflect.Proxy
。前任:
Proxy.newProxyInstance(iClazz.getClassLoader(),
new Class[]{iClazz},
new YourInvocationHandler())
iClazz
is the class of your interface and YourInvocationHandler
is an instance of java.lang.reflect.InvocationHandler
iClazz
是你的接口的类,YourInvocationHandler
是一个实例java.lang.reflect.InvocationHandler
回答by Bozho
commons-proxyaims at simplifying the task.
commons-proxy旨在简化任务。
What you want is an invoker proxy (without a target object). So you can use:
你想要的是一个调用代理(没有目标对象)。所以你可以使用:
ProxyFactory factory = new JavassistProxyFactory();
Object result =
factory.createInvokerProxy(invoker, new Class[] {YourInterface.class});
And your invoker
must implement the Invoker
interface, whose invoke
method will be called on each method invocation. (4 times the word "invoke" here)
并且您invoker
必须实现该Invoker
接口,该接口的invoke
方法将在每次方法调用时被调用。(此处“调用”一词的 4 次)
Note that commons-proxy uses the preferred underlying proxying mechanism - in the above example it's javassist.
请注意,commons-proxy 使用首选的底层代理机制——在上面的例子中它是 javassist。
However, you seem to need the proxy for mocking purposes. With mockitothis is as easy as:
但是,您似乎需要代理来进行模拟。使用mockito这很简单:
YourInterface yourMock = mock(YourInterface.class);
when(yourMock.someMethod()).thenReturn(yourPreferredResult);
回答by Arne Deutsch
If you are only interesting in mocking I would suggest to use a framework.
如果您只对模拟感兴趣,我建议您使用框架。
EasyMock ( http://easymock.org/) or JMock ( http://www.jmock.org/) might fit.
EasyMock ( http://easymock.org/) 或 JMock ( http://www.jmock.org/) 可能适合。
To create a proxy yourself you can use the class java.lang.reflect.Proxy
.
要自己创建代理,您可以使用 class java.lang.reflect.Proxy
。
回答by Thorbj?rn Ravn Andersen
Exampledepot has a simple snippet for how to create an interface proxy based on java.lang.reflect.proxy
at http://exampledepot.8waytrips.com/egs/java.lang.reflect/ProxyClass.html
Exampledepot对如何创建一个基于接口代理一个简单的片断java.lang.reflect.proxy
在http://exampledepot.8waytrips.com/egs/java.lang.reflect/ProxyClass.html
You just need to provide functionality for the invoke(Object proxy, Method m, Object[] args)
in your own code.
您只需要invoke(Object proxy, Method m, Object[] args)
在您自己的代码中为 提供功能。
EDIT: Based on comments it appears that the class you do not want is the interfaceclass, not the implementationclass. In that case there is no way around byte code manipulation. You may want to look at Javassist which contains a snippet compiler.
编辑:根据评论,您不想要的类似乎是接口类,而不是实现类。在这种情况下,字节码操作是无法解决的。您可能想查看包含片段编译器的 Javassist。
回答by Stathis Alexopoulos
In your code i did the following
在您的代码中,我执行了以下操作
// return thisMethod.invoke(self, args);
return null;
and i got the following result
我得到了以下结果
Handling public abstract void org.rege.instruments.IPerson.setName(java.lang.String) via the method handler
Is this what did you wanted? As you can see the OutOfMemory was produced by a recursive call to your invoke.
这是你想要的吗?正如您所看到的, OutOfMemory 是由对您的调用的递归调用产生的。