黑马程序员:Java基础总结----静态代理模式&动态代理

来源:互联网 发布:java中方法的格式 编辑:程序博客网 时间:2024/05/18 03:50
黑马程序员: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 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

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

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

public interface InvocationHandler 方法摘要
 Objectinvoke(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培训、期待与您交流!

原创粉丝点击