首页 > 其他 > 详细

【设计模式】——代理模式

时间:2015-11-13 22:05:30      阅读:281      评论:0      收藏:0      [点我收藏+]

代理模式:

    代理模式为其他的对象增加一个代理对象,进行访问控制。从而避免直接访问一个对象,造成效率或者安全性上的降低。去掉了某些功能,或提供了某些格外的服务。

应用场景:

     1 远程代理,为一个远程对象,创建一个本地的代理对象。每次访问,直接访问本地代理对象即可。

  2 虚拟代理,如果对象很大,直接访问开销很大,可以为他创建一个代理对象,只生成关键的信息即可。

  3 保护代理,(权限控制)为某个对象增加一种保护机制,只有一定的权限才能通过这个代理,访问后面的对象。

  4 智能引用代理,提供目标对象一些额外的服务。

一、静态代理

  被代理类和代理类通过继承相同的接口。

1.创建Movable接口

public interface Movable {
    public void move();
}

2.创建被代理类,实现了Movable接口

public class Car implements Movable {

    @Override
    public void move() {
        try {            
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽车行驶中……");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

3.创建一个时间的代理类,实现了Movable接口

public class TimeProxy implements Movable{
    
    public TimeProxy(Movable m) {
        super();
        this.m = m;
    }
    private Movable m;
    @Override
    public void move() {
        long startTime = System.currentTimeMillis();
        System.out.println("汽车开始行驶");
        m.move();
        long endTime = System.currentTimeMillis();
        System.out.println("汽车开始行驶,行驶时间为:"+(endTime-startTime)+"毫秒");
    }
    
}

4.如果存在多个代理类,如一个日志的代理类

public class LoggerProxy implements Movable{
    
    public LoggerProxy(Movable m) {
        super();
        this.m = m;
    }

    private Movable m;
    
    @Override
    public void move() {
        System.out.println("开始记录日志");
        m.move();
        System.out.println("记录日志结束");
    }

}

5.客户端调用

public class Client {
    public static void main(String[] args) {
        Car car = new Car();
        TimeProxy time = new TimeProxy(car);
        LoggerProxy log = new LoggerProxy(time);
        log.move();
    }
}

6.结果显示

                                  技术分享

二、动态代理

1、省略静态代理的1,2步骤。即已经有了movable接口和car类

2、创建时间代理,并且继承了 InvocationHandler 接口,实现了invoke()方法。在invoke()方法的前后增加业务逻辑。

public interface InvocationHandler{  
  Object invoke(Object proxy, Method method, Object[] args)  
         throws Throwable;  
} 

 1. proxy就是通过 Proxy.newProxyInstance()方法创建的动态代理类,它实现了指定的interfaces接口。 通常这个对象在invoke函数中不使用。

   2. Method 表示动态代理类所实现的接口中的方法。通过 Method 对象可以获取方法名、参数类型、返回类型等信息。

   3. Object[] args 包含了传入动态代理类所实现的方法的参数值。

public class TimeProxy implements InvocationHandler {

    public TimeProxy(Object target) {
        super();
        this.target = target;
    }

    Object target;
    
    /**参数:
     * proxy:被代理的对象
     * method:被代理的方法
     * arg:方法的参数
     * 返回object对象
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] arg)
            throws Throwable {
        long startTime = System.currentTimeMillis();
        System.out.println("汽车开始行驶");
        method.invoke(target);
        long endTime = System.currentTimeMillis();
        System.out.println("汽车行驶结束,行驶时间为:"+(endTime-startTime)+"毫秒");
        return null;
    }

3.客户调用,用到Proxy类中的newProxyInstance()方法,使用Proxy.newProxyInstance()方法创建动态代理类,方法定义:

public static Object newProxyInstance(ClassLoader loader,  
                                      Class<?>[] interfaces,  
                                      InvocationHandler h)  
  1. ClassLoader :加载动态代理类的类加载器
  2. interfaces   :该动态代理类所要实现的接口
  3. InvocationHandler:事件处理,转发所有的方法调用代理。
  4. 函数返回创建的代理类,实现了interfaces接口
public class Client {
    public static void main(String[] args) {
        Car car = new Car();
        Class<?>cls = car.getClass();
        TimeProxy handle = new TimeProxy(car);
        /*
         * 参数分别为
         */
        Movable m = (Movable) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),handle);
        m.move();
    }
}

4.运行结果为

                            技术分享

三、运用cglib生成代理

1.引用cglib-nodep-2.1_3 jar包

2.创建一个类,如Car

public class Car {
    public void move(){
        System.out.println("汽车行驶中……");
    }
}

3.创建一个cglib代理。通过获得动态代理,拦截所有目标类方法的调用

public class CglibProxy implements MethodInterceptor {
    
    private Enhancer enhancer = new Enhancer();
    
    //获得动态代理
    public Object getProxy(Class cls){
        enhancer.setSuperclass(cls);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    
    //拦截所有目标类方法的调用
    @Override
    public Object intercept(Object obj, Method method, Object[] arg,
            MethodProxy proxy) throws Throwable {
        //添加业务逻辑
        System.out.println("开始记录日志");
        proxy.invokeSuper(obj, arg);
        System.out.println("记录日志结束");
        return null;
    }

}

4.Client客户端

public class Client{

    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
        Car car = (Car) proxy.getProxy(Car.class);
        car.move();
    }

}

5.运行结果

                                     技术分享

具体原理待完善……因为我还没有完全搞明白!

【设计模式】——代理模式

原文:http://www.cnblogs.com/doudingbest/p/4963249.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!