学习JDK的动态代理前需要了解静态代理的实现,假设我们有一个接口Moveable,一个类BMW,通过静态代理的方式获取汽车行驶的时间。

一、静态代理

(1)Moveable接口,有个move()方法

package guoli.proxy;

/**
 * @author zhangguoli.cn
 * @date 2018/2/9
 */
public interface Moveable {
    void move();
}

(2)类BMW实现了Moveable接口

package guoli.proxy;

import java.util.Random;

/**
 * @author zhangguoli.cn
 * @date 2018/2/9
 */
public class BMW implements Moveable {
    @Override
    public void move() {
        try {
            System.out.print("汽车行驶中...");
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

(3) TimeCar实现了对BMW行驶的时间记录

package guoli.proxy;

/**
 * @author zhangguoli.cn
 * @date 2018/2/9
 */
public class TimeCar extends BMW {

    @Override
    public void move() {
        System.out.println("汽车开始行驶");
        Long startTime = System.currentTimeMillis();
        super.move();//调用被代理类BMW的move()方法
        Long endTime = System.currentTimeMillis();
        System.out.println("汽车行驶结束... 用时:" + (endTime-startTime) + "毫秒!");
    }
}

(4) 测试类BMWTest

package guoli.proxy;

/**
 * @author zhangguoli.cn
 * @date 2018/2/9
 */
public class BMWTest {
    public static void main(String[] args) {
        TimeCar timeCar = new TimeCar();
        timeCar.move();
    }
}

输出结果大致如下:

汽车开始行驶
汽车行驶中...
汽车行驶结束... 用时:768毫秒!

如果后来Ford也需要记录行驶时间,就需要增加一个FordTime记录Ford的行驶时间;如果需要增加对车行驶距离的记录,还需要增加Distance类记录相关信息。


二、动态代理

JDK动态代理 只能代理实现了某些接口的类。

代理模式的UML类图:

来源网络,侵删

(1)使用JDK的动态代理首先要实现InvocationHandler接口,并在invoke()方法增加处理逻辑

直白点说就是对被代理的类要实现什么额外的操作

package guoli.JDKProxy;

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

/**
 * @author zhangguoli.cn
 * @date 2018/2/9
 */
public class TimeHandler implements InvocationHandler {

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

    /**
     * @param proxy 被代理的对象
     * @param method 被代理对象的方法
     * @param args 被代理对象方法的参数
     * @return Object对象
     * @throws Throwable
     */
    @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;
    }
}

(2)和静态代理一样需要一个接口Moveable和实现接口的类BMW

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

(3)通过Proxy.newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h)创建一个代理类,通过代理调用被代理类的方法

public class Test {
    public static void main(String[] args) {
        BMW bmw = new BMW();
        InvocationHandler handler = new TimeHandler(bmw);
        Class<?> cls = bmw.getClass();
        /**
         * loader 类加载器
         * interfaces 实现的接口
         * handler Handler
         */
        Moveable m = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),handler);
        m.move();
    }
}

标签: Java, 动态代理

添加新评论