Java中带有动态接口的代理
我正在尝试将一些C#
代码移植到Java
,但代理实现遇到了问题
我有这门课:
public class Comic
{
public int ComicID;
private List<Volume> _volumes;
public List<Volume> GetVolumes()
{
return _volumes;
}
public void SetVolumes(List<Volume> volumes)
{
_volumes = volumes;
}
}
我试图为这个实体的特定方法调用添加一个拦截器,但我还需要访问它的字段,因为我将使用它们
在研究了如何在Java中实现代理之后,我发现:
public void Load(Class<?> type)
{
// - type is a Comic.class
ClassLoader appLoader = this.getClass().getClassLoader();
MyProxyHandler proxyHandler = new MyProxyHandler();
Object proxy = Proxy.newProxyInstance(appLoader, new Class[] { ComicInterface.class }, proxyHandler);
}
问题是,type
是动态的,所以我不知道哪个是动态的,而且我不希望代码要求所有东西都有接口,所以我查看了如何build a dynamic interface:
public class InterfaceLoader extends ClassLoader
{
public InterfaceLoader(ClassLoader loader)
{
super(loader);
}
public Class<?> GetInterface(Class<?> type) throws Exception
{
String interfaceName = type.getName() + "$Proxy";
Class<?> interfaceType = null;
interfaceType = findLoadedClass(interfaceName);
if (interfaceType != null) { return interfaceType; }
// - According to the link
byte[] classData = new InterfaceBuilder().BuildInterface(interfaceName, type.getDeclaredMethods());
return defineClass(interfaceName, classBytes, 0, classBytes.length);
}
}
然后我会把它和代理一起使用:
public void Load(Class<?> type)
{
// - type is a Comic.class
ClassLoader appLoader = this.getClass().getClassLoader();
InterfaceLoader loader = new InterfaceLoader(appLoader);
Class<?> dynamicInterface = loader.GetInterface(type);
// - dynamicInterface on debug is "console.Comic$Proxy", seems fine
MyProxyHandler proxyHandler = new MyProxyHandler();
Object proxy = Proxy.newProxyInstance(appLoader, new Class[] { dynamicInterface }, proxyHandler);
}
我得到的例外是
java.lang.IllegalArgumentException: interface console.Comic$Proxy is not visible from class loader
我查找了这个异常,但只找到了两种解决方案,即确保名称与任何类型都不冲突(我确信不会冲突),以及使用this.getClass().getClassLoader()
而不是type.getClass().getClassLoader()
(相同的错误)
我做错了什么
另一个问题是,如何获取“原始”对象,以便从ComicID
等字段获取/设置值?使用上面的代理方法,我可以很好地拦截方法,但我无法访问它的字段
我读过关于获取InvocationHandler的here,但我不知道如何从处理程序中获取对象,我找不到一个例子
# 1 楼答案
只有一个类加载器可以看到动态生成的接口,那就是InterfaceLoader加载器。通过将错误传递给newProxyInstance,可能可以消除错误
但是,我很确定这对你没有任何好处。您正在编写的java代码都不是由该类加载器加载的,因此,除非通过反射,否则无法通过该接口调用
如果你想使用代理,那么你必须让Comic实现一个接口,然后在任何地方使用该接口。在这种情况下,下一个问题的答案是将原始对象的一个实例传递给代理处理程序构造函数
如果你真的想做这个动态拦截的事情,你可能想看看使用ASM(http://asm.ow2.org/)或Javaassist来构建Comic的动态子类,它覆盖你想要拦截的方法,而不是使用代理