java复习之动态代理

来源:互联网 发布:淘宝服务器时间 编辑:程序博客网 时间:2024/06/15 16:56

在某些情况下,我们不希望或是不能直接访问对象 A,而是通过访问一个中介对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理。这里对象 A 所属类我们称为委托类,也称为被代理类,对象 B 所属类称为代理类。代理优点有:

隐藏委托类的实现
解耦,不改变委托类代码情况下做一些额外处理,比如添加初始判断及其他公共操作
根据程序运行前代理类是否已经存在,可以将代理分为静态代理和动态代理。

由开发人员编写或是编译器生成代理类的方式都属于静态代理​;​

代理类在程序运行前不存在、运行时由程序动态生成的代理方式称为动态代理。​

实现动态代理包括三步:

(1). 新建委托类;(2). 实现InvocationHandler接口,这是负责连接代理类和委托类的中间类必须实现的接口;(3). 通过Proxy类新建代理类对象。

2.1 新建委托类

public interface Operate {

public void operateMethod1();public void operateMethod2();public void operateMethod3();

}

public class OperateImpl implements Operate {

@Overridepublic void operateMethod1() {    System.out.println("Invoke operateMethod1");    sleep(110);}@Overridepublic void operateMethod2() {    System.out.println("Invoke operateMethod2");    sleep(120);}@Overridepublic void operateMethod3() {    System.out.println("Invoke operateMethod3");    sleep(130);}private static void sleep(long millSeconds) {    try {        Thread.sleep(millSeconds);    } catch (InterruptedException e) {        e.printStackTrace();    }}

}
Operate是一个接口,定了了一些函数,我们要统计这些函数的执行时间。
OperateImpl是委托类,实现Operate接口。每个函数简单输出字符串,并等待一段时间。
动态代理要求委托类必须实现了某个接口,比如这里委托类OperateImpl实现了Operate,原因会后续在微博公布。

2.2. 实现 InvocationHandler 接口

public class TimingInvocationHandler implements InvocationHandler {

private Object target;public TimingInvocationHandler() {}public TimingInvocationHandler(Object target) {    this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    long start = System.currentTimeMillis();    Object obj = method.invoke(target, args);    System.out.println(method.getName() + " cost time is:" + (System.currentTimeMillis() - start));    return obj;}

}
target属性表示委托类对象。

InvocationHandler是负责连接代理类和委托类的中间类必须实现的接口。其中只有一个

public Object invoke(Object proxy, Method method, Object[] args)
函数需要去实现,参数:
proxy表示下面2.3 通过 Proxy.newProxyInstance() 生成的代理类对象。
method表示代理对象被调用的函数。
args表示代理对象被调用的函数的参数。

调用代理对象的每个函数实际最终都是调用了InvocationHandler的invoke函数。这里我们在invoke实现中添加了开始结束计时,其中还调用了委托类对象target的相应函数,这样便完成了统计执行时间的需求。
invoke函数中我们也可以通过对method做一些判断,从而对某些函数特殊处理。

2.3. 通过 Proxy 类静态函数生成代理对象

public class Main {
public static void main(String[] args) {
// create proxy instance
TimingInvocationHandler timingInvocationHandler = new TimingInvocationHandler(new OperateImpl());
Operate operate = (Operate)(Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[] {Operate.class},
timingInvocationHandler));

    // call method of proxy instance    operate.operateMethod1();    System.out.println();    operate.operateMethod2();    System.out.println();    operate.operateMethod3();}

}
这里我们先将委托类对象new OperateImpl()作为TimingInvocationHandler构造函数入参创建timingInvocationHandler对象;
然后通过Proxy.newProxyInstance(…)函数新建了一个代理对象,实际代理类就是在这时候动态生成的。我们调用该代理对象的函数就会调用到timingInvocationHandler的invoke函数(是不是有点类似静态代理),而invoke函数实现中调用委托类对象new OperateImpl()相应的 method(是不是有点类似静态代理)。

public static Object newProxyInstance(ClassLoader loader, Class

0 0
原创粉丝点击