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

How to get 'proxied' object from an existing dynamic proxy

有没有像Proxy.getProxiedObject()这样的API,会return动态代理的原始对象?例如,我想在代理对象上调用 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 可用于此;但是我使用 API 构建了一个解决方法,它从任何 Proxy 对象中检索 InvocationHandler,以及测试 Class 是否为 [=14= 的对象] class:

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

    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:

        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 实用程序 class,所有逻辑和新的 API 都位于其中。 class 甚至可以扩展到包括 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