如何在Java中创建接口的代理?
如何在不创建实现接口的类的情况下为接口创建代理?
我有一个具体的例子:我有一个接口,联系人,需要创建一个充当联系人的代理对象。该代理对象将用于运行一些 TestNG 测试。
我尝试过使用 JDK 方法,但只能找到需要实际实现该接口的示例。
我还发现 jasssist 可能会帮助我解决这个问题,并尝试实现一个简单的示例,该示例似乎一直有效,直到出现内存不足错误。这是我正在做的事情的一个片段:
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);
}
};
}
请记住,createMock() 方法的参数将是一个接口。
谢谢
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.
I have tried using the JDK approach but could find only examples that needed an actual implementation of that interface.
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:
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.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
exampledepot 在 http://exampledepot.8waytrips.com/egs/java.lang.reflect/ProxyClass.html
您只需为
invoke 提供功能(对象代理,方法 m,Object[] args)
在您自己的代码中。编辑:根据评论,您不需要的类似乎是接口类,而不是实现类。在这种情况下,就没有办法绕过字节码操作。您可能想查看包含代码片段编译器的 Javassist。
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.htmlYou just need to provide functionality for the
invoke(Object proxy, Method m, Object[] args)
in your own code.EDIT: Based on comments it appears that the class you do not want is the interface class, not the implementation class. In that case there is no way around byte code manipulation. You may want to look at Javassist which contains a snippet compiler.
您可以使用
java.lang.reflect.Proxy
的newProxyInstance
方法。例如:
iClazz
是接口的类,YourInvocalHandler
是java.lang.reflect.InvocalHandler
的实例You can use the method
newProxyInstance
ofjava.lang.reflect.Proxy
.Ex:
iClazz
is the class of your interface andYourInvocationHandler
is an instance ofjava.lang.reflect.InvocationHandler
commons-proxy 旨在简化任务。
您想要的是一个调用者代理(没有目标对象)。因此您可以使用:
并且您的
invoker
必须实现Invoker
接口,其invoke
方法将在每次方法调用时调用。 (此处“调用”一词的 4 倍)请注意,commons-proxy 使用首选的底层代理机制 - 在上面的示例中它是 javassist。
但是,您似乎需要代理来进行模拟目的。使用 mockito 就这么简单:
commons-proxy aims at simplifying the task.
What you want is an invoker proxy (without a target object). So you can use:
And your
invoker
must implement theInvoker
interface, whoseinvoke
method will be called on each method invocation. (4 times the word "invoke" here)Note that commons-proxy uses the preferred underlying proxying mechanism - in the above example it's javassist.
However, you seem to need the proxy for mocking purposes. With mockito this is as easy as:
如果您只对模拟感兴趣,我建议使用框架。
EasyMock ( http://easymock.org/ ) 或 JMock ( http://www.jmock.org/ )可能适合。
要自己创建代理,您可以使用
java.lang.reflect.Proxy
类。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.
To create a proxy yourself you can use the class
java.lang.reflect.Proxy
.在您的代码中,我执行了以下操作
,得到了以下结果
这是您想要的吗?
如您所见,OutOfMemory 是由对您的调用的递归调用产生的。
In your code i did the following
and i got the following result
Is this what did you wanted?
As you can see the OutOfMemory was produced by a recursive call to your invoke.