一、 动态代理
Ø 关于这个动态代理,理论上来说呢,我是不想多说什么的,但是这里不得不说点什么,为什么呢?嗯……这么说吧!这个玩意听过很多此了,但是一直都是没有搞清楚,而且是那种连门门都没有摸到的那种不清楚,所以这次专门花了点时间,就是为了搞一搞这个哥们。
Ø 说起这个动态代理的proxy这个东西,就不得不说这个装饰者模式。什么叫装饰者模式呢?很简单就是装逼还得让别人知道的模式,其实就是干预别人程序的运行。这里来举个例子:
l List集合是一个接口,它呢有好几个实现类,我们就随便用一个就是ArrayList做其实现类。
l 然后呢List接口有一个方法是add,这个方法呢返回值类型是void,意思就是没有返回值类型。所以呢,当我们向集合使用add方法添加元素的时候,就不知道元素是否成功的添加进去了没有?
l 于是,我们就自己写一个类,然后封装一个方法,方法里面写上add方法添加元素,然后在从集合中获取元素,与放进去之前的元素对比是否有相等的。如果有返回true,没有返回false。但是这样条用很明显是不方便。
l 于是我们就可以使用代理类来代理。使用List的add方法的时候同时可以判断是否添加成功。
Ø 这个代理怎么实现呢,于是就使用到了这个proxy的newProxyInstance方法,参数传入有加载器,用来加载类和对象。然后就是接口的Class对象数组,也就是说某一个实现类的接口Class对象数组。最后一个参数是代理实例的调用处理程序实现的接口,我们需要自己写一个类来实现这个类,当然也可以使用匿名内部类,直接在方法上进行实现。接下来我就分开来一个一个的说。
staticObject newProxyInstance(ClassLoaderloader,Class>[] interfaces, InvocationHandlerh)
l loader - 定义代理类的类加载器
1. 类加载器是负责加载类的对象。将class文件(硬盘)加载到内存生成Class对象。类加载其分为三种。我们主要使用的是程序加载器,对自己的程序进行加载,所以这里获取加载就是直接使用getClassLoader();
a) 启动类加载器主要加载的是JVM自身需要的类,这个类加载使用C++语言实现的,是虚拟机自身的一部分,它负责将
b) 扩展类加载器是指Sun公司(已被Oracle收购)实现的sun.misc.Launcher$ExtClassLoader类,由Java语言实现的,是Launcher的静态内部类,它负责加载
c) 程序加载器是指Sun公司实现的sun.misc.Launcher$AppClassLoader。它负责加载系统类路径java -classpath或-D java.class.path 指定路径下的类库,也就是我们经常用到的classpath路径,开发者可以直接使用系统类加载器,一般情况下该类加载是程序中默认的类加载器,通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器。
l interfaces - 代理类要实现的接口列表
1. 这个要怎么说呢?总的来说,我们使用这个动态代理类proxy的时候,前提就是必须接口,因为我们代理的是接口,实现接口的类,返回实现接口的对象。总的来说就是代理接口的实现类,返回一个接口对象。但是这里的参数是接口的Class对象数组,重点是数组,也就是说可以代理实现多个接口,为什么呢,因为我们的一个实现类虽然只能继承一个,但是却可以实现多个接口。这样我们就可以同时代理实现多个接口。
l h - 指派方法调用的调用处理程序
1. 这个才是最重要的地方。h是InvocationHandler接口的实现类对象,这个接口在API文档的解释是这个样子的。“是代理实例的调用处理程序 实现的接口。”好像挺难以理解的。我的理解是这个样子的,上面不是有一堆接口吗?那么这个“代理实例”就是这些个接口的实现类,那么“调用的处理程序”就是调用这个实现类的方法程序,最后一句“实现的接口”就是说,这个方法程序前提肯定是封装在一个类中,它的意思就是封装这个类必须是InvocationHandler这个接口的实现类。那么这句话就解释完毕了。总结起来就是要告诉我们的意思就是………………………………你要代理实现某个类的接口,就必须自己写一个类,这个类要实现InvocationHandler接口,然后在自己写的这个类中实现接口方法,那么这个方法就可以代理实现接口的类增加一些功能。
2. 该接口要实现的方法:Object invoke(Object proxy, Method method, Object[] args)
a) proxy - 在其上调用方法的代理实例
i. 这个可以理解为动态代理类proxy为这些接口实现的对象,不过这个对象没有实现任何的方法体。从晚上收集的资料显示,这个对象确实是没有什么作用,唯一的作用就是返回接口的本类对象来实现连续调用。
b) method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
i. 这个就比较简单了,很明显,这个指的就是你代理实现接口之后的方法的Method对象。利用这个对象可以执行接口实现类的实现对应的方法。保证动态代理。
c) args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如java.lang.Integer 或 java.lang.Boolean)的实例中。
d) 当然这个就更没有什么说的,这个就是方法的参数,没有参数就可以忽略这个变量数组。