【发布时间】:2015-10-25 01:20:07
【问题描述】:
我正在尝试将一些 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 是动态的,所以我不知道哪个会是动态的,而且我不希望代码具有所有接口的要求,所以我查找了如何@987654321 @:
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() 而不是 @ 987654332@(同样的错误)。
我做错了什么?
另一个问题是,如何获取“原始”对象,以便从 ComicID 等字段获取/设置值?使用上述代理方法,我可以很好地拦截方法,但我无法访问它的字段。
我已经阅读了here 以获取 InvocationHandler,但我不知道如何从处理程序中获取对象,也找不到使用它的示例。
【问题讨论】:
-
不要把真正的问题埋在代码里。
-
您实际上想在这里完成什么?很可能有一种更简单和/或预先存在的方法来处理它。
-
@chrylis 这是来自 C# 代码的端口,我生成原始对象的“副本”,继承原始对象,但增加了拦截任何方法调用的能力(例如用于记录或延迟加载)。现在想起来,我发现 Java 有一个动态代理构建器很好,但由于它只适用于接口,它与创建一个继承原始类的动态类不同......
-
@Daniichi 听起来您正在寻找的是 AspectJ 之类的东西,或者如果代理可以接受,则可能是 Spring AOP。 AspectJ 和基于 cglib 的 AOP 都可以使用实际的类,只要所讨论的类和方法不是最终的。