gpt4 book ai didi

java - 允许动态代理转换到任何兼容的接口(interface)。不管

转载 作者:行者123 更新时间:2023-11-29 09:10:14 25 4
gpt4 key购买 nike

在处理类中的特定方法时,我制作了一个动态代理作为中间人。我这样做是为了避免必须覆盖我需要控制的每个接口(interface)中的每个方法。

没有人会理解或关心的 Waffley 位(但可能会为问题添加更多上下文):

在我要给出的例子中,我试图让它变得通用,这样你就可以自己编译它来测试和运行,但在真实情况下,我有这样的事情:

interface CommandSender

interface ConsoleCommandSender extends CommandSender
interface Player extends CommandSender

如果我要代理 ConsoleCommandSender例如,生成的代理应该可以转换为 CommandSender .实际上,ConsoleCommandSender没有用 getInterfaces() 列出其所有接口(interface)这发生了:

java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender

Player 类没有这个问题,并且总是可转换为 CommandSender .

真正的问题:

因此,使用以下代码作为起点,如何才能成功地转换由 myProxy 表示的代理?到所需的格式,而不必担心 ClassCastException

下面的代码将成功编译和运行,但希望你能理解我通过转换为 List 得到的结果。而不是 ArrayList .

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

public class ProxyClass implements InvocationHandler {

private Object classProxy;

public static void main(String[] args) {
// Example declaration
// (I know the proxy should really be cast as an ArrayList
// but this is my point, it SHOULD work anyway)
ArrayList methodObject = new ArrayList<String>();
List<String> myProxy = (List<String>)ProxyClass.newInstance(methodObject, false);

// Example usage
myProxy.add("Hello World!");
System.out.println(myProxy.get(0));
}

public static Object newInstance(Object proxy, boolean silent) {
return Proxy.newProxyInstance(
proxy.getClass().getClassLoader(),
proxy.getClass().getInterfaces(),
new ProxyClass(proxy));
}

private ProxyClass(Object proxy) {
this.classProxy = proxy;
}

// Is called whenever a method is invoked
public Object invoke(Object p, Method m, Object[] args) throws Throwable {
return m.invoke(classProxy, args);
}

}

在我关于这个问题的初步部分的另一个线程中,一个人评论说我可以使用 <T>变量将另一个有效接口(interface)添加到列表中。虽然我真的不明白如何实现它,但这似乎是一个好的开始。

最佳答案

我不是 100% 确定我承认我理解你的问题 -您希望能够“直接”转换为 ArrayList?我的意思是 -

    ArrayList<String> myProxy = (ArrayList<String>)ProxyClass.newInstance(methodObject, false);

这对你不起作用。原因是生成的对象不是ArrayList的instant。从某种意义上说,这种行为类似于装饰器。
装饰器是它装饰的对象的实例吗?不,它们符合相同的接口(interface)。
你应该做的是考虑使用 CGLIB .CGLIB 让您为类创建代理(拦截对象)。
CGBLib 的代理对象确实是代理对象的一个​​实例。
如果我没记错的话,Hibernate 使用 CGLib 和 ASM 来代理实体对象,
可以看到here我用 CGLIB 做的一些实验的链接。

关于java - 允许动态代理转换到任何兼容的接口(interface)。不管,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12861756/

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