使用jdk的动态代理非常简单,主要是在创建动态代理类的时候,传入三个参数Proxy.newProxyInstance(loader, interfaces, h);我们不仅要知道要传这个参数,还要知道为什么要传入这三个参数,第一个和第二个是类加载器和被代理对象实现的所有接口,在生成代理对象之前,会先判断缓存中是否存在代理对象,如果存在就直接返回。判断缓存中是否存在代理对象的时候就会用到类加载器(loader)和接口(interfaces),如果缓存中没有代理对象,就会生成一个代理对象,这个代理对象会继承Proxy类并且会实现被被代理对象所实现的所有接口。这个代理类还会有一个只有InvocationHandler类的构造函数。newProxyInstance内部就是根据反射找到代理类的构造函数,然后把InvocationHandler这个类掺入代理类中,然后利用反射再次生成代理类对象,这样就完成了。下面就贴出关键代码:
// 这里是生成class的地方
- Class<?> cl = getProxyClass0(loader, intfs);
- // 使用我们实现的InvocationHandler作为参数调用构造方法来获得代理类的实例
- try {
- final Constructor<?> cons = cl.getConstructor(constructorParams);
- final InvocationHandler ih = h;
- //这就是调用构造函数生成动态代理类
- return cons.newInstance(ih);
- } catch (NoSuchMethodException e) {
- throw new InternalError(e.toString());
- }
接下来在看一下生成的代理类对象
public final class $Proxy1 extends Proxy
implements Dog
{
public $Proxy1(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
}
很明显看出这个类继承了Proxy类和实现了Dog接口并且有一个只有一个参数的构造函数。这个代理会实现Dog接口中的所有方法,
public final void eat()
throws
{
try
{
this.h.invoke(this, m4, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
当调用代理类的eat方法时,实际上执行的是InvovcationHandler的invoke方法