zoukankan      html  css  js  c++  java
  • 黑马程序员:Java基础总结----静态代理模式&动态代理

    黑马程序员:Java基础总结



    静态代理模式&动态代理

      ASP.Net+Android+IO开发 .Net培训 、期待与您交流!




    静态代理模式
    public  class  Ts {
            public  static  void  main(String[] args)  throws  Exception {
                  // 通过中介公司生产一批衣服
                ClothingProduct cp =  new  ProxCompany( new  LiNingCompany());
                cp.productClothing();
          }

    }

    /**
     * 定义生产一批衣服功能的接口
     *
     */
    interface  ClothingProduct {

            void  productClothing();  // 有生产一批衣服的功能

    }

    /**
     *
     * 代理类:中介公司
     *
     */
    class  ProxCompany  implements  ClothingProduct {

            private  ClothingProduct  cp  ;  // 中介公司不会生产衣服,需要找一家真正能生产衣服的公司

          ProxCompany(ClothingProduct cp) {
                  super ();
                  this . cp  = cp;
          }

            @Override
            public  void  productClothing() {

                System.  out .println( "收取1000块钱的中介费"  );
                  cp .productClothing();

          }

    }

    /**
     *
     * 李宁公司是生产服装的目标类
     *
     */
    class  LiNingCompany  implements  ClothingProduct {

            @Override
            public  void  productClothing() {

                System.  out .println( "生产一批衣服。。。。"  );
          }

    }

    上面程序的做法,使用的模式是静态代理模式

     

    静态代理模式在现实编程中的弊端:

    它的特征是代理类和目标对象的类都是在编译期间确定下来的,不利于程序上的扩展,上面示例中,如果客户还想找一个“生产一批鞋子”的工厂,那么还需要新增加一个代理类和一个目标类。如果客户还需要很多其他的服务,就必须一一的添加代理类和目标类。那就需要写很多的代理类和目标类


    动态代理技术

    java.lang.reflect
    类 Proxy

    Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

    构造方法摘要
    protected Proxy(InvocationHandler h)
              使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例。
    字段摘要
    protected  InvocationHandler h
              此代理实例的调用处理程序。
    方法摘要
    static InvocationHandler getInvocationHandler(Object proxy)
              返回指定代理实例的调用处理程序。
    static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
              返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。
    static boolean isProxyClass(Class<?> cl)
              当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。
    static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
              返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

    每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

    public interface InvocationHandler 方法摘要
     Object invoke(Object proxy, Method method, Object[] args)
              在代理实例上处理方法调用并返回结果。
    参数:
    proxy - 在其上调用方法的代理实例
    method - 对应于在代理实例上调用的接口方法的  Method 实例。 Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
    args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为  null。基本类型的参数被包装在适当基本包装器类(如  java.lang.Integer 或  java.lang.Boolean)的实例中。
    返回:
    从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为  null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出  NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出  ClassCastException

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

    public  class  Ts {
            public  static  void  main(String[] args)  throws  Exception {
                 ArrayList test =  new  ArrayList();
                  // 代理只可以强转换成接口
                 Collection list = (Collection ) getProxy(test,  new  MyAdvice());
                 list.add(123);
                 list.add(123);
                System.  out .println(list);

          }

            public  static  Object getProxy( final  Object target,  final  Advice adv) /* 终态是因为内部类调用 */  {
                  // 返回一个指定接口的代理类实例 obj
                Object obj = Proxy. newProxyInstance(
                  // 定义代理类的类加载器
                            target.getClass().getClassLoader(),
                              // 代理类要实现的接口列表
                            target.getClass().getInterfaces(),
                              // 指派方法调用的调用处理程序 InvocationHandler
                              new  InvocationHandler() {

                                    @Override
                                    public  Object invoke(Object proxy, Method method,
                                              Object[] args)  throws  Throwable {                         
                                        adv.begintime(method);
                                          //target目标 ,args方法参数,调用原来的方法
                                        Object retVal = method.invoke(target, args);
                                        adv.endtime(method);
                                          return  retVal;
                                  }
                            });

                  return  obj;
          }
    }
    //插入的建议接口
    interface  Advice {
            void  begintime(Method method);

            void  endtime(Method method);
    }
    //我的建议
    class  MyAdvice  implements  Advice {

            @Override
            public  void  begintime(Method method) {
                Long time = System. currentTimeMillis();
                System.  out .println(method.getName() + time);
          }

            @Override
            public  void  endtime(Method method) {
                Long time = System. currentTimeMillis();
                System.  out .println(method.getName() + time);
          }

    }

    一个更巧妙的方法:自定义一个处理程序
    public  class  Ts {
            public  static  void  main(String[] args)  throws  Exception {
                ProxyHandler handler=  new  ProxyHandler();
                 ClothingProduct cp2=(ClothingProduct)handler.newProxyInstance(  new  LiNingCompany());
                cp2.productClothing();

          }

    }

    class  ProxyHandler  implements  InvocationHandler {

            /* 目标对象 */
            private  Object  target  ;

            /* 创建目标对象的代理对象 */
            public  Object newProxyInstance(Object target) {

                  this . target  = target;

                  /*
                 * 第一个参数:定义代理类的类加载器
                 * 第二个参数:代理类要实现的接口 列表
                 * 第三个参数:指派方法调用的调用处理程序
                 */
                  return  Proxy.newProxyInstance( this .  target .getClass().getClassLoader(),
                              this . target  .getClass().getClasses(),  this );

          }

            @Override
            public  Object invoke(Object proxy, Method method, Object[] args)
                        throws  Throwable {

                Object result =  null ;

                System.  out .println( "目标对象上的方法调用之前可以添加其他代码。。。"  );
                result = method.invoke(  this . target  , args);  // 通过反射调用目标对象上的方法
                System.  out .println( "目标对象上的方法调用之后可以添加其他代码。。。"  );

                  return  result;
          }

    }







      ASP.Net+Android+IO开发 .Net培训 、期待与您交流!

  • 相关阅读:
    Newton's Method in C#
    bat中的注释符
    Oracle query and backup
    Oracle Essentials
    修改Oracle 10g数据库字符集
    Some awareness before migrating from x86 to x64
    DataTable 那些事(二)
    很赞的PHP字符串加密函数
    PayPal 注册和使用详解
    ASP网站session超时,后台操作超时,重新登陆
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3190060.html
Copyright © 2011-2022 走看看