黑马程序员: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培训 、期待与您交流!

原文地址:https://www.cnblogs.com/dyllove98/p/3190060.html