您的位置:首页 > 编程语言 > Java开发

Java动态代理简单实例:老板与秘书

2017-02-26 22:38 344 查看
Java动态代理是Java中比较晦涩难懂的一个部分,虽然看了一些别人的博客之后觉得自己大体明白了,但是事非经过不知难,自己写的时候却产生了诸多疑问。

本文用尽可能简单的例子来说明Java动态代理的机制。

例子共四个部分:

1. ReadFile接口(批改文件)

2. Boss类,委托类,能够批改文件

3. Secretary类,没有实现ReadFile接口,用Secretary可创建代理类,“代理”Boss批改文件(创建出来的代理类对象就是main函数中的secretary1)

4. Main类

1. ReadFile接口

public interface ReadFile {
public void read();
}


2. Boss类,实现了ReadFile接口,可以批改文件

public class Boss implements ReadFile {

@Override
public void read() {
System.out.println("I'm reading files.");
}

}


3. Secretary类,不是代理类,但利用这个类能创建出代理类

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

public class Secretary implements InvocationHandler {

private Object object;

public Secretary(Object object) {
this.object = object;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("I'm secretary.");
Object result = method.invoke(object, args);

return result;
}

}


Secretary类中有一个变量object用来存boss对象,因为接下来Secretary要代理Boss做的事,因此先要把boss对象先保存起来。

Secretary类如果想代理Boss做的事,即调用Boss类的方法,必须实现InvocationHandler,重载invoke方法,然后在invoke函数中调用Boss类的方法。

我们看到invoke函数中有一句method.invoke(object, args),代理类就是用这种方式调用委托类的方法。

4. Main类

import java.lang.reflect.Proxy;

public class Main {

public static void main(String[] args) {
ReadFile boss = new Boss();

InvocationHandler handler = new Secretary(boss);

ReadFile secretary = (ReadFile) Proxy.newProxyInstance(
boss.getClass().getClassLoader(),
boss.getClass().getInterfaces(),
handler);

secretary.read();
}
}
整个函数的执行流程如下:

先是创建了一个boss对象,

然后创建一个handler对象,

然后利用handler构造出一个能调用boss方法的对象secretary,这个secretary就是代理类对象

执行最后一句时,代理类的public Object invoke(...)方法被调用,代理类在此处调用委托类的方法,method.invoke()先打印I'm secretary,再调用boss对象的方法read()。



secretary每调用一次read()时都会执行public Object invoke(...),显而易见传入的第二个参数method即read(),第三个参数args即传入read()的参数(这里没有)。

实现了InvocationHandler的Secretary类并不能直接调用委托类的方法,handler对象只是一个handler,只有当handler对象用newProxyInstance方法包裹成secretary对象后,才具有调用boss方法的能力。

既然说secretary是由handler包裹而成的,那secretary是什么类型的呢?

System.out.println(secretary.getClass().getName());



类型是$Proxy0

如果文章中存在问题请及时指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: