gpt4 book ai didi

java - 如何从现有动态代理获取 'proxied'对象

转载 作者:行者123 更新时间:2023-12-02 11:20:46 24 4
gpt4 key购买 nike

是否有像Proxy.getProxiedObject()这样的API,可以返回动态代理的原始对象?例如,我想在代理对象上调用 equals,而不是在动态代理本身上调用 equals,如下例所示:

public class ProxyTest implements InvocationHandler {

public static Object createProxy(Object target) {
Class<? extends Object> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new ProxyTest());
}

public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
// PROXIED OBJECTS COMPARISON - DESIRED
// return Proxy.getProxiedObject(proxy).equals(Proxy.getProxiedObject(args[0]));

// DYNAMIC PROXIES COMPARISON - UNDESIRED
// return proxy.equals(args[0]);

return null;
}

public static void main(String[] args) {
Object proxied = createProxy(new Object());
System.out.println(proxied.equals(proxied));
}
}

最佳答案

我认为没有任何可用的 API;但我使用检索 InvocationHandler 的 API 构建了一个解决方法来自任何Proxy对象,以及测试 Class 是否存在的对象是 Proxy类:

使用这些我创建了 InvocationHandler 的抽象扩展保留对代理对象的引用,并使用静态实用程序从任何潜在中检索代理对象 Proxy对象,以及用于创建 Proxy 的工厂实用程序使用目标对象:

    public abstract class ProxiedSavedInvocationHandler implements InvocationHandler {
public static Object getProxied(Object proxy) {
if (!Proxy.isProxyClass(proxy.getClass()))
return null;

InvocationHandler handler = Proxy.getInvocationHandler(proxy);
return (handler instanceof ProxiedSavedInvocationHandler) ?
((ProxiedSavedInvocationHandler)handler).proxied : null;
}

protected final Object proxied;

public ProxiedSavedInvocationHandler(Object proxied) {
this.proxied = proxied;
}

public Object getProxied() {
return proxied;
}

public Object createProxy() {
Class<? extends Object> clazz = proxied.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
}

然后我就使用了新创建的类,如下所示:

        class MyProxiedSavedInvocationHandler extends ProxiedSavedInvocationHandler {
...
}

ProxiedSavedInvocationHandler handler = new MyProxiedSavedInvocationHandler(target);
Object proxy = handler.createProxy();

// DESIRED API THROUGH STATIC UTILIY
Object proxied1 = ProxiedSavedInvocationHandler.getProxied(proxy);

// DESIRED API THROUGH INSTANCE UTILIY
Object proxied2 = handler.getProxied();

对此解决方案的唯一依赖是 ProxiedSavedInvocationHandler所有逻辑和新 API 所在的实用程序类。此类甚至可以扩展为包含将行为委托(delegate)给其他人的 API InvocationHandler透明;但最低要求是有的。

以下是此解决方案的完整工作示例应用程序:


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {

static class MyProxiedSavedInvocationHandler extends ProxiedSavedInvocationHandler {
public MyProxiedSavedInvocationHandler(Object proxied) {
super(proxied);
}

public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
if (!method.getName().equals("equals"))
return method.invoke(proxied, args);

Object other = ProxiedSavedInvocationHandler.getProxied(args[0]);
System.out.println("====");
System.out.println("\tRunning 'equals' inside proxy with:");
System.out.println("\tthis: " + proxied);
System.out.println("\tother: " + other);
System.out.println("====");
return proxied.equals(other);
}
}

static abstract class ProxiedSavedInvocationHandler implements InvocationHandler {
public static Object getProxied(Object proxy) {
if (!Proxy.isProxyClass(proxy.getClass()))
return null;

InvocationHandler handler = Proxy.getInvocationHandler(proxy);
return (handler instanceof ProxiedSavedInvocationHandler) ?
((ProxiedSavedInvocationHandler)handler).proxied : null;
}

protected final Object proxied;

public ProxiedSavedInvocationHandler(Object proxied) {
this.proxied = proxied;
}

public Object getProxied() {
return proxied;
}

public Object createProxy() {
Class<? extends Object> clazz = proxied.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
}

// TO TEST EDGE SCENARIONS
private static Object createProxy(Class<? extends Object> clazz, InvocationHandler handler) {
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), handler);
}

// MAIN
public static void main(String[] args) {
// EDGE SCENARIOS
Object proxiedFromNotEnhancedProxy =
ProxiedSavedInvocationHandler.getProxied(createProxy(Object.class, (p, m, a) -> null));
Object proxiedFromNotAProxy =
ProxiedSavedInvocationHandler.getProxied(new Object());
System.out.println("proxied from NOT ENHANCED PROXY: " + proxiedFromNotEnhancedProxy);
System.out.println("proxied from NOT A PROXY: " + proxiedFromNotAProxy);
System.out.println();

// FUNCTIONALITY DESIRED
Object target = new Object();
ProxiedSavedInvocationHandler handler = new MyProxiedSavedInvocationHandler(target);

Object proxy = handler.createProxy();
Object proxied1 = ProxiedSavedInvocationHandler.getProxied(proxy);
Object proxied2 = handler.getProxied();

System.out.println("target: " + target);
System.out.println("proxied1: " + proxied1);
System.out.println("target == proxied1: " + (target == proxied1));
System.out.println("proxy.equals(proxy): " + proxy.equals(proxy));
}
}

Complete code on GitHub

关于java - 如何从现有动态代理获取 'proxied'对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56121919/

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