• Java动态代理


               代理是基本的设计模式之一,它是为了提供额外的或不同的操作,而插入的用来代理"实际"对象的对象。这些操作通常涉及与”实际“对象的通信,因此代理通常充当着中间人的角色。下面的一个用例展示代理结构的简单示例。

      接口:

    /**
     * 接口
     * @author Arts&Crafts
     *
     */
    public interface Interface {
        void doSomething();
        void somethingElse(String arg);
    }

      实际类:

     1 /**
     2  * 实际类
     3  * @author Arts&Crafts
     4  *
     5  */
     6 public class RealObject implements Interface {
     7 
     8     @Override
     9     public void doSomething() {
    10         System.out.println("RealObject.doSomething()");
    11     }
    12 
    13     @Override
    14     public void somethingElse(String arg) {
    15         System.out.println("RealObject.somethingElse() " + arg);
    16     }
    17 
    18 }

      代理类:

     1 /**
     2  * 代理类
     3  * 
     4  * @author Arts&Crafts
     5  * 
     6  */
     7 public class SimpleProxy implements Interface {
     8     private Interface proxied;
     9 
    10     public SimpleProxy(Interface proxy) {
    11         this.proxied = proxy;
    12     }
    13 
    14     @Override
    15     public void doSomething() {
    16         System.out.println("SimpleProxy.doSomething()");
    17         proxied.doSomething();
    18     }
    19 
    20     @Override
    21     public void somethingElse(String arg) {
    22         System.out.println("SimpleProxy.somethingElse() " + arg);
    23         proxied.doSomething();
    24     }
    25 
    26 }

      测试:

     1 public class SimpleProxyDemo {
     2 public static void consumer(Interface iface){
     3     iface.doSomething();
     4     iface.somethingElse("Hello World");
     5 }
     6     
     7     /**
     8      * @param args
     9      */
    10     public static void main(String[] args) {
    11         consumer(new RealObject());
    12         System.out.println();
    13         consumer(new SimpleProxy(new RealObject()));
    14     }
    15 
    16 }

      因为consumer()接受的Interface,所以它无法知道正在获取的到底是RealObject还是SimpleProxy,因为这二者都实现了Interface。但是SimpleProxy已经被插入到客户端和RealObkect之间,因此它会执行操作,然后调用RealObject上相同的方法。

      在任何时刻,只要你想要将额外的操作从“实际”对象中分离到不同的地方,特别是当你希望能够很容易地做出修改,从没有使用额外操作转换为使用这些操作,或者反过来,代理就显得很有用(设计模式的关键是封装修改——因此你需要修改事务以证明这种模式的正确性)。例如,如果你希望跟踪对RealObject中的方法的调用,或者希望度量这些调用的开销,那么你应该怎么样做呢?这些代码肯定是你不希望将其并到运用中的代码,因此代理使得你可以很容易地添加或移除它们。

      Java的动态代理比代理的思想更向前迈进了一步,因为它可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所在的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相应的对策。下面是用动态代理重写:

      动态代理调用处理器类:

     1 import java.lang.reflect.InvocationHandler;
     2 import java.lang.reflect.Method;
     3 
     4 public class DynamicProxyHandler implements InvocationHandler {
     5     private Object proxied;
     6 
     7     public DynamicProxyHandler(Object proxied) {
     8         this.proxied = proxied;
     9     }
    10 
    11     @Override
    12     public Object invoke(Object proxy, Method method, Object[] args)
    13             throws Throwable {
    14         System.out.println("*** proxy:" + proxy.getClass() + ". method: "
    15                 + method + ". args:" + args);
    16         if (args != null)
    17             for (Object arg : args)
    18                 System.out.println("  " + arg);
    19         Object result = method.invoke(proxied, args);
    20         return result;
    21     }
    22 
    23 }

         测试类:

     1 import java.lang.reflect.Proxy;
     2 
     3 import org.jdk.staticproxy.Interface;
     4 import org.jdk.staticproxy.RealObject;
     5 
     6 public class SimpleDynamicProxyDemo {
     7     public static void consumer(Interface iface) {
     8         iface.doSomething();
     9         iface.somethingElse("Hello World");
    10     }
    11 
    12     public static void main(String[] args) {
    13         RealObject real = new RealObject();
    14         consumer(real);
    15         System.out.println();
    16         Interface proxy = (Interface) Proxy.newProxyInstance(
    17                 Interface.class.getClassLoader(),
    18                 new Class[] { Interface.class }, new DynamicProxyHandler(real));
    19         consumer(proxy);
    20     }
    21 }

      通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要得到一个类加载器(你通常可以从已经被加载的对象中获取其类加载器,然后传递给它),一个你希望该代理实现的接口列表(不是类或抽象类),以及InvocationHandler接口的一个实现。动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造器传递给一个“实际”对象的引用,从而使得调用处理器在执行其中任务时,可以将请求转发。

      invoke()方法中传递进来了代理对象,以放你需要区分请求的来源,但是在很多情况下,帮你并不关心这一点。然而,在invoke()内部,在代理上调用方法时需要格外当心,因为对接口的调用将被重定向为对代理的调用。

      

        

  • 相关阅读:
    2.安卓体系结构
    1.Android的历史与安装
    Mysql免安装配置
    安装gulp
    搭建vue开发环境的步骤
    运行一个从GitHub上下载的vue项目的具体步骤
    网站源码,大量HTML5模板,视频源码,黑客技术资源
    bootstrap文件树
    jQuery unbind 某个function
    响应式设计的思考:媒体查询(media query)
  • 原文地址:https://www.cnblogs.com/ArtsCrafts/p/DynamicProxy.html
Copyright © 2020-2023  润新知