一、Java动态代理的实现方式
Java动态代理有两种方式实现
1、首先得到代理类,然后创建代理实例
InvocationHandler handler = new InvocationHandlerImpl(..);
// 1、得到指定接口代理类的Class
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... });
// 2、得到代理类的构造函数
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });
// 3、通过构造函数对象创建动态代理类实例
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });
2、一步到位,直接获取代理实例
// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..);
// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader,
new Class[] { Interface.class },
handler );
其实两种方式的本质一样,只是第二种是对第一种的一种封装罢了。
原理:我们指定这种实现是得到指定接口的代理类,然后我们的目标类也是实现这个接口,所以它必须针对接口而言。
实质:得到一个实现指定接口的类的class字节码
举个例子:
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), new Class[] { Collection.class});
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });
Collection Proxy = (Collection) constructor.newInstance(new InvocationHandler[] { handler });
我们可以这样理解:
1、Proxy.getProxyClass(Collection.class.getClassLoader(), new Class[] { Collection.class})得到下面类Proxy0的字节码。
2、clazz.getConstructor(new Class[] { InvocationHandler.class })得到类Proxy0的构造函数
3、constructor.newInstance(new InvocationHandler[] { handler })创建了类Proxy0的实例。
下面这个类Proxy0类的字节码在调用Proxy.getProxyClass()的时候会生成,下面将它以java代码的形式展现,实质在生成的时候,内部的实现是直接得到它的class文件,然后将它进行加载得到对应的Class。
import java.lang.reflect.InvocationHandler;
import java.util.Collection;
import java.util.Iterator;
public class Proxy0 implements Collection {
private InvocationHandler mHandler;
public Proxy0(InvocationHandler handler) {
mHandler = handler;
}
@Override
public int size() {
int result = 0;
try {
result = (int) mHandler.invoke(this, Collection.class.getMethod("size", null), null);
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean isEmpty() {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("isEmpty", null), null);
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean contains(Object o) {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("contains", Object.class), new Object[]{o});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public Iterator iterator() {
Iterator result = null;
try {
result = (Iterator) mHandler.invoke(this, Collection.class.getMethod("iterator", null), null);
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public Object[] toArray() {
Object[] result = null;
try {
result = (Object[]) mHandler.invoke(this, Collection.class.getMethod("toArray", null), null);
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public Object[] toArray(Object[] a) {
Object[] result = null;
try {
result = (Object[]) mHandler.invoke(this, Collection.class.getMethod("toArray", Object[].class), new Object[]{a});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean add(Object o) {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("add", Object.class), new Object[]{o});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean remove(Object o) {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("remove", Object.class), new Object[]{o});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean containsAll(Collection c) {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("containsAll", Collection.class), new Collection[]{c});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean addAll(Collection c) {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("addAll", Collection.class), new Collection[]{c});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean removeAll(Collection c) {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("removeAll", Collection.class), new Collection[]{c});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public boolean retainAll(Collection c) {
boolean result = false;
try {
result = (boolean) mHandler.invoke(this, Collection.class.getMethod("retainAll", Collection.class), new Collection[]{c});
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
@Override
public void clear() {
try {
mHandler.invoke(this, Collection.class.getMethod("clear", null), null);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
可以看到,我们在调用代理类Proxy0对应的方法的时候,实质调用的是InvocationHandler的invoke方法,也就是代理类的所有方法都会走InvocationHandler的invoke方法这个通道,而InvocationHandler实例是我们创建代理类Proxy0的时候传进去的,具体实现是我们自己来处理,所以我们在invoke方法里面不仅可以调用目代理标类实例方法而且可以添加自己的业务处理。
下面举个例子:
public class ProxyTest {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), new Class[] { Collection.class});
Constructor constructor = clazz.getConstructor(InvocationHandler.class);
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new ArrayList(), new Callable() {
@Override
public void beforeCall() {
System.out.println("beforeCall");
}
@Override
public void afterCall() {
System.out.println("afterCall");
}
});
Collection proxy = (Collection) constructor.newInstance(new InvocationHandler[] { myInvocationHandler });
System.out.println(proxy.add("Hello"));
}
}
class MyInvocationHandler<T> implements InvocationHandler {
private T mTarget;
private Callable mCallable;
public MyInvocationHandler(T t, Callable c) {
mTarget = t;
mCallable = c;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
mCallable.beforeCall();
result = method.invoke(mTarget, args);
mCallable.afterCall();
return result;
}
}
interface Callable {
void beforeCall();
void afterCall();
}
上面代理思路可以用如下类图表示。
ArrayList是目标类,Proxy0是ArrayList的代理类。
调用过程如下:
调用Proxy0中的方法都会对应调用InvocationHandler的invoke方法,在invoke方法中调用目标类ArrayList的对应方法和额外操作。
为了使整个代理思想更加清晰,我们下面进行一下封装。
public class ProxyClass implements InvocationHandler {
private Object mTarget;
private Callable mCallable;
// 对指定对象绑定一个代理对象
public Object bind(Object target, Callable callable) {
this.mTarget = target;
this.mCallable = callable;
//取得代理对象
return Proxy.newProxyInstance(mTarget.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result=null;
callable.beforeCall();
//执行方法
result=method.invoke(target, args);
callable.afterCall();
return result;
}
}
interface Callable {
void beforeCall();
void afterCall();
}
public class TestProxy {
public static void main(String[] args) {
// 创建代理对象
ProxyClass proxy = new ProxyClass();
// 为代理指定目标对象和额外处理回调
Collection collectionProxy = (Collection) proxy.bind(new ArrayList(), new Callable() {
@Override
public void beforeCall() {
System.out.println("beforeCall");
}
@Override
public void afterCall() {
System.out.println("afterCall");
}
});
// 使用代理来调用目标类的函数
collectionProxy.add("Hello");
}
}