【问题标题】:How to get 'proxied' object from an existing dynamic proxy如何从现有的动态代理中获取“代理”对象
【发布时间】:2019-12-06 10:44:13
【问题描述】:

是否有类似Proxy.getProxiedObject() 的API 可以返回动态代理的原始对象?例如,我想在代理对象上调用 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));
    }
}

【问题讨论】:

    标签: java algorithm design-patterns reflection aop


    【解决方案1】:

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

    使用这些我创建了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 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();
    

    对这个解决方案的唯一依赖是拥有所有逻辑和新 API 所在的 ProxiedSavedInvocationHandler 实用程序类。此类甚至可以扩展为包含 API,以透明地将行为委托给其他 InvocationHandlers;但最低要求就在那里。

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

    
    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 2011-05-23
      • 2023-03-16
      • 2022-11-07
      • 2011-11-20
      相关资源
      最近更新 更多