设计模式之代理模式(静态代理和JDK动态代理)

 

一、什么是代理

代理模式定义

为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。

常见的代理模式

远程代理:为不同地理的对象提供局域网待办对象,通过远程代理可以监控各个店铺使之能直观的了解店内信息。

虚拟代理:根据需要将资源消耗很多的对象进行延迟,真正需要的时候进行创建。

智能引用代理又分为静态代理和动态代理两种。下面重点介绍一些静态代理和动态代理。

二、静态代理

1.静态代理:代理和被代理对象在代理之前是确定的,他们都实现相同的接口或者继承相同的抽象类。具体的UML关系图如下所示:

2.静态代理的实现。现在模拟汽车在行驶过程中的示例。在汽车行驶前后增加“汽车开始行驶”和“汽车结束行驶”的日志,并在最后统计输出汽车行驶的时间。

Moveable接口

public interface Moveable {
    void move();
}

在这里Car类是实现了Moveable接口的被代理类 

public class Car implements Moveable {
    @Override
    public void move() {


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


    }
}
CarTimeProxy类是代理对象
public class CarTimeProxy implements Moveable {

    private Moveable m;
    public CarTimeProxy(Moveable m){
        super();
        this.m = m;
    }
    @Override
    public void move() {
        long startTime = System.currentTimeMillis();
        System.out.println("汽车开始行驶....");
        m.move();
        long endTime = System.currentTimeMillis();
        System.out.println("汽车结束行驶...汽车行驶时间:"+(endTime-startTime)+"ms!");
    }
}

测试类:

public class Client {

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

    }
}

三、动态代理

动态代理:动态产生代理,实现对不同类,不同方法的代理。

动态代理的实现方式有两种,一种是JDK动态代理,另外一种是CGLIB动态代理。

JDK动态代理和CGLIB动态代理区别

JDK动态代理

1.只能代理实现了接口的类

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

CGLIB动态代理

1.针对类来实现代理的

2.对指定目标类产生一个子类,通过方法拦截技术拦截所有父类方法的调用。

在这里重点介绍以下JDK的动态代理。

JDK动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

(1)Interface InvocationHandler:该接口中仅定义了一个方法

public object invoke(Object obj,Method method,Object[] args)在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。

(2)Proxy:该类即为动态代理类

static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在接口中声明过的方法)

所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,该class需要实现一组interface,使用动态代理,必须实现InvocationHandler接口。

动态代理步骤
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法,创建一个代理类
   newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)
4.通过代理调用方法

具体代码实现:

1、需要动态代理的接口:复用上面的Moveable接口

2.需要代理的对象:复用上面的Car类

3.创建一个实现了InvocatHandler的类

public class TimeHandler implements InvocationHandler {

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

    }

    /**
     *
     * @param proxy 被代理对象
     * @param method 被代理对象方法
     * @param args 方法的参数
     * @return 返回值
     * @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("汽车结束行驶...\n汽车行驶时间:"+(endTime-startTime)+"ms");
        return  null;
    }
}

4.客户端测试类,通过 Proxy的newProxyInstance方法,生成代理对象。

public class Client {

    public static void main(String[] args) {
        Car car = new Car();
        InvocationHandler handler = new TimeHandler(car);
        Class<? extends Car> cls = car.getClass();
        Moveable moveable = (Moveable) Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),handler);
        moveable.move();

    }
}

在这里多说一下,Java的JDK动态代理,也是Spring的AOP的实现原理。

猜你喜欢

转载自blog.csdn.net/lovebaby1689/article/details/113544886