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