Java动态代理简释
我们利用java的Proxy类写一个动态代理的小例子很简单,但是我们对它的实现不是很理解,这里的不理解大概有两处,newProxyInstance方法和传入的classloader、Class、还有我们实现的handler,有两大难点:
1、 我们不知道它内部是怎么生成代理类的
2、 我们不知道在我们自己编写的处理器中实现的invoke方法是在哪由谁调用的
下面我简单的说说关于这两点。
一、再从Proxy的newProxyInstance()入手,在这个源码方法中,抓取支干代码,有很重要的几行:
Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams);
InvocationHandler ih = h;
return newInstance(cons, ih);
从上面返回的newInstance()方法我们可以看出,内部利用反射的方法再调用相应的构造器方法生成的代理类中有我们传入的handler,源码中newInstance方法还有两层,这里就不说了,因此到这里我们就不难理解前面我们提到的生成的代理类中为什么存在我们自己编写的handler了。
二、利用反编译工具查看Proxy类动态创建的代理类,可以知道这个类实现了我们传入的接口的所有方法,当我们利用生成的代理类调用接口中相应的方法时,也就是使用多态调用其中方法,如hill.goHill();
public static void main(String[] args) { Play pl = new Play(); MyInvocationHandler mh = new MyInvocationHandler(pl); Hill hill = (Hill) Proxy.newProxyInstance(pl.getClass().getClassLoader(),pl.getClass().getInterfaces(),mh); hill.goHill(); hill.backHill(); }
其实这个方法调的是我们传入的那个handler中的方法。下面就是一个该生成的代理类中的一个源方法码例子。
public final void goHill(String paramString) throws { try { h.invoke(this, m3, new Object[] { paramString }); return; } catch (RuntimeException localRuntimeException) { throw localRuntimeException; } catch (Throwable localThrowable) { } throw new UndeclaredThrowableException(localThrowable); }
其中h就我们传入的handler实现类。
下面是我自己写的handler的代码,该方法是从InvocationHandler中实现的,以前不知道实现的invoke方法在哪调用,被谁调用,现在我们可以知道,其实底层实际是被它自己调用的,由上面的方法源码可知,invoke方法是在生成的代理对象的相应方法中被handler调用。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {
System.out.println("此路是我开,此树是我栽,要想从此过,留下买路财。");
obj = method.invoke(hill,args);//
System.out.println("小子,需要帮助随时call哥哥。。。。\n");
return obj;}
我们可以看出invoke方法找中并没有调用proxy,为什么还要存在呢?于是网上查了一下,处理器中的invoke里的第一个参数proxy,它的作用有两点:
1.可以使用反射获取代理对象的信息(也就是proxy.getClass().getName())。
2.可以将代理对象返回以进行连续调用,这就是proxy存在的目的。