设计模式之代理模式

静态代理概念及其实现


代理和被代理对象在代理之前是确定的,他们都实现了相同的接口或者继承了相同的抽象类。


package com.ql.proxy;

import java.util.Random;

public class Car implements Moveable {

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

}
package com.ql.proxy;

public class Car2 extends Car {

    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        super.move();
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:" 
                + (endtime - starttime) + "毫秒!");
    }


}
package com.ql.proxy;

public class Car3 implements Moveable {

    public Car3(Car car) {
        super();
        this.car = car;
    }

    private Car car;

    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        car.move();
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:" 
                + (endtime - starttime) + "毫秒!");
    }

}
package com.ql.proxy;

public class Client {

    /**
     * 测试类
     */
    public static void main(String[] args) {
//      Car car = new Car();
//      car.move();
        //使用集成方式
//      Moveable m = new Car2();
//      m.move();
        //使用聚合方式实现
        Car car = new Car();
        Moveable m = new Car3(car);
        m.move();
    }

}
package com.ql.proxy;

public interface Moveable {
    void move();
}

聚合比继承更适合代理模式

package com.ql.proxy;

import java.util.Random;

public class Car implements Moveable {

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

}
package com.ql.proxy;

public class CarLogProxy implements Moveable {

    public CarLogProxy(Moveable m) {
        super();
        this.m = m;
    }

    private Moveable m;

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

}
package com.ql.proxy;

public class CarTimeProxy implements Moveable {

    public CarTimeProxy(Moveable m) {
        super();
        this.m = m;
    }

    private Moveable m;

    @Override
    public void move() {
        long starttime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        m.move();
        long endtime = System.currentTimeMillis();
        System.out.println("汽车结束行驶....  汽车行驶时间:" 
                + (endtime - starttime) + "毫秒!");
    }

}
package com.ql.proxy;

public class Client {

    /**
     * 测试类
     */
    public static void main(String[] args) {
        Car car = new Car();
        CarLogProxy clp = new CarLogProxy(car);
        CarTimeProxy ctp = new CarTimeProxy(clp);
        ctp.move();
    }

}
package com.ql.proxy;

public interface Moveable {
    void move();
}

JDK动态代理

实现步骤:

  1. 创建一个实现接口InvocationHandler的类,它必须实现invoke方法
  2. 创建被代理的类以及接口
  3. 调用Proxy的静态方法,创建一个代理类newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
  4. 通过代理调用方法
package com.ql.proxy;

import java.util.Random;

public class Car implements Moveable {

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

}
package com.ql.proxy;

public interface Moveable {
    void move();
}
package com.ql.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler {

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

    private Object target;

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

}
package com.ql.jdkproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import com.imooc.proxy.Car;
import com.imooc.proxy.Moveable;

public class Test {

    /**
     * JDK动态代理测试类
     */
    public static void main(String[] args) {
        Car car = new Car();
        InvocationHandler h = new TimeHandler(car);
        Class cls = car.getClass();
        /**
         * loader  类加载器
         * interfaces  实现接口
         * h InvocationHandler
         */
        Moveable m = (Moveable)Proxy.newProxyInstance(cls.getClassLoader(),
                                                cls.getInterfaces(), h);
        m.move();
    }

}

使用 cglib 动态产生代理

需要的jar包下载(点我)

package com.ql.cglibproxy;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz){
        //设置创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);

        return enhancer.create();
    }

    /**
     * 拦截所有目标类方法的调用
     * obj  目标类的实例
     * m   目标方法的反射对象
     * args  方法的参数
     * proxy代理类的实例
     */
    @Override
    public Object intercept(Object obj, Method m, Object[] args,
            MethodProxy proxy) throws Throwable {
        System.out.println("日志开始...");
        //代理类调用父类的方法
        proxy.invokeSuper(obj, args);
        System.out.println("日志结束...");
        return null;
    }

}
package com.ql.cglibproxy;

public class Client {

    /**
     * @param args
     */
    public static void main(String[] args) {

        CglibProxy proxy = new CglibProxy();
        Train t = (Train)proxy.getProxy(Train.class);
        t.move();
    }

}
package com.ql.cglibproxy;

public class Train {

    public void move(){
        System.out.println("火车行驶中...");
    }
}

JDK动态代理

  1. 只能代理实现了接口的类
  2. 没有实现接口的类不能实现JDK的动态代理

CGLIB动态代理

  1. 针对类来实现代理
  2. 对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用

模拟JDK代理的内部实现

需要的jar包下载

Demo源码下载


你可能感兴趣的:(工厂模式,设计模式,实例,设计模式)