Java 代理模式
代理模式
目标类和代理类,不是直接调用目标类对象,而是通过调用代理类的对象的方法,代理类来帮我们访问目标类对象,这样我们就可以在代理类上添加更多需要的扩展功能,而目标类不用改动,只用实现自身的主要功能。
代理类是为了扩展目标类的功能,代理类和目标类的产出结果应该相同,所以为了确保代理类和目标类的返回类型一致,最好使用接口来约束代理类和目标类。
使用接口而不是继承,也减少了目标类和代理类间的耦合,并且在动态代理中,动态生成的代理类会自动去继承 Proxy 类,而Java是单继承所以不行,而且需要使用反射来获取目标类的接口来创建代理类实例, 如果被代理对象没有实现接口,则无法通过接口来定义代理对象需要实现的方法
动态代理
在Java中可以通过Proxy.newProxyInstance()方法创建动态代理类的实例。
而与静态代理不同的是,静态是在程序运行前就已经存在代理类的字节码文件,也就是说,事先就写好了代理类的源码并编译,动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成。并且目标对象是固定的,代理类一般会持有一个目标类的对象引用(即作为成员变量。
在运行期间动态创建实例
动态代理,通俗点说就是:无需声明式的创建java代理类,而是在运行过程中生成"虚拟"的代理类,被ClassLoader加载。从而避免了静态代理那样需要声明大量的代理类。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{...}
ClassLoader loader:用于指定一个类加载器,用来加载代理类,通常使用当前类的类加载器
Class<?>[] interfaces:目标类的接口列表,指定生成的代理长什么样子,也就是有哪些方法
InvocationHandler h:InvocationHandler是一个接口,所以可以使用匿名内部类并重写对应方法invoke(),用来指定生成的代理对象要干什么事情,在调用代理类的方法时会自动调用该方法。
java动态代理中的invoke方法是如何被自动调用的