Java中具有动态接口的代理

Java中具有动态接口的代理,java,proxy,Java,Proxy,我试图将一些C代码移植到Java中,但代理实现遇到了问题 我有这门课: public class Comic { public int ComicID; private List<Volume> _volumes; public List<Volume> GetVolumes() { return _volumes; } public void SetVolumes(List<Volume> v

我试图将一些
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;
    }
}
然后我将它与代理一起使用:

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);
}
我查找了异常,但只找到了两种解决方案,即确保名称与任何类型都不冲突(我确信不会冲突),以及使用
this.getClass().getClassLoader()
而不是
type.getClass().getClassLoader()
(相同错误)

我做错了什么

另一个问题是,如何获取“原始”对象,以便从
ComicID
等字段获取/设置值?使用上面的代理方法,我可以很好地拦截方法,但我无法访问它的字段


我读过关于获取InvocationHandler的文章,但是我不知道如何从处理程序中获取对象,我找不到一个例子。

只有一个类加载器可以看到动态生成的接口,那就是InterfaceLoader加载器。您可以通过将错误传递给newProxyInstance来消除错误

但是,我很确定这对你没有任何好处。您正在编写的java代码没有一个是由该类加载器加载的,因此您将无法通过该接口调用,除非通过反射

如果您想使用代理,那么您必须让Comic实现一个接口,然后在任何地方都使用该接口。在这种情况下,下一个问题的答案是将原始对象的实例传递给代理处理程序构造函数


如果你真的想做这个动态拦截的事情,你可能想看看使用ASM()或Javaassist来构建一个动态的Comic子类,它覆盖了你想要拦截的方法,而不是使用代理。

不要把实际的问题隐藏在代码中。你到底想在这里实现什么?很可能有一种更简单和/或预先存在的方法来处理它。@chrylis它是一个C代码的端口,我生成了原始对象的“副本”,继承了原始对象,但增加了拦截任何方法调用的能力(例如日志记录或延迟加载)。现在回想一下,我发现Java有一个动态代理生成器很不错,但因为它只与接口一起工作,所以它与创建一个继承原始的动态类不同…@danichi听起来像是您要寻找的是AspectJ,或者如果代理是可接受的,可能是Spring AOP。只要所讨论的类和方法不是最终的,基于AspectJ和cglib的AOP都可以处理实际的类。
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