gpt4 book ai didi

java - Java 中的代理具有动态接口(interface)

转载 作者:行者123 更新时间:2023-12-02 09:19:07 26 4
gpt4 key购买 nike

我正在尝试将一些 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 是动态的,所以我不知道哪个会是动态的,而且我不希望代码要求拥有所有接口(interface),所以我查找了如何 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);
}

我得到的异常(exception)是

java.lang.IllegalArgumentException: interface console.Comic$Proxy is not visible from class loader

我查找了异常,但只找到了两个解决方案,即确保名称不与任何类型冲突(我确信它不会),并使用 this.getClass().getClassLoader() 而不是 type.getClass().getClassLoader() (相同错误)。

我做错了什么?

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

我已经阅读了关于 here 来获取 InvocableHandler 的内容,但我不知道如何从处理程序中获取该对象,而且我找不到它的示例。

最佳答案

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

但是,我很确定这对你没有任何好处。您正在编写的 Java 代码都不会由该类加载器加载,因此您将无法通过该接口(interface)进行调用(除非通过反射)。

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

如果你真的想做这个动态拦截的事情,你可能想考虑使用 ASM ( http://asm.ow2.org/ ) 或 Javaassist 构建一个覆盖你想要拦截的方法的 Comic 动态子类,而不是使用代理.

关于java - Java 中的代理具有动态接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33325144/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com