二、Java动态代理
Proxy:专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。
对于某些对象,需要在他的方法执行前做一些别的事情,这时,我们需要用到动态代理。(将方法的执行交给别人来做)。
下面是个人写的代码。
执行结果:
掌握Java动态代理的关键是理解两样东西:
Proxy类和InvocationHandler接口
Proxy:
中文意思代理人,意思是以委托人的名义做一件委托人想做的事情。
它有一个静态方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
第一个参数是他要代理的对象的类加载器;
第二个参数是他要代理的对象的借口数组;
第三个是他要代理的内容的具体细则,类型是一个InvocationHandler接口;
第三个参数很好理解,毕竟代理人总会比自己做的更好一点,所以代理人具体怎么做还是需要写清楚的。
而前两个参数是干嘛的呢?
这里需要知道的一点就是代理的对象在被代理后会形成一个新的对象,后文称代理实例。
而代理实例的创建就需要前两个参数。打开Proxy找到newProxyInstance静态方法。
***final Class<?>[] intfs = interfaces.clone();***---------------------710行
这一句是对接口的Class数组进行clone()----------------这里不知道问什么要这么做。
***Class<?> cl = getProxyClass0(loader, intfs);***---------------------719行
这一句是通过被代理对象的类加载器和接口的Class数组创建具体代理类的Class对象,在获取到这个Class对象后,根据反射机制我们可以通过构造器去生成一个代理实例。
***final Constructor<?> cons = cl.getConstructor(constructorParams);***---------------------729行
在上一句的基础上,我们要拿到一个构造器,而拿哪个构造器,这就是问题所在!!
我继续往上寻找这个参数constructorParams是干嘛的(第233行),发现他是一个Class[]静态常量,而它的值是{ InvocationHandler.class };
这个常量的注释如下:
/** parameter types of a proxy class constructor */ 大致意思是:代理类构造函数的参数类型
在掌握反射机制之后,通过拿到的cons构造器,我们能够构造出一个具体实例,也就是这个函数的额返回值。
return cons.newInstance(new Object[]{h});
这一句是通过构造器生成具体实例并返回。
InvocationHandler接口:
实现这个接口的类要实现一个叫invoke的函数。对于这个实现类,一般情况下要定义一个public Object变量obj。
public Object invoke(Object proxy, Method method, Object[] args) invoke中文:调用
第一个参数到现在暂时还不知道有什么用。有知道的大佬麻烦写一次,谢谢哇。
第二参数是一个Method对象,根据中文意思,可以理解为在这个obj的方法被调用时,调用这个函数。
第三个参数是调用方法时传入的的参数。