Java中的代理(Proxies in Java)
来源:互联网 发布:java获取response对象 编辑:程序博客网 时间:2024/04/29 04:58
最近在看《Core Java》的过程中,觉得代理的部分书中写的不是很清晰,例子举的也不是很好理解,就在网上查了一份不错的讲解Java中的Proxy的资料(资料:Proxies in Java,是一份英文资料,讲解的非常清楚,我有写的不明白的地方大家可以再好好看看这里面是怎么讲的),顺便在这做个笔记。
首先要注意:代理 —- 代理的是接口(interface),而不是类(class)或是抽象类(abstract)
我们要代理的接口如下
/*** Interface IVehicle.*/public interface IVehicle { public void start(); public void stop(); public void forward(); public void reverse(); public String getName();}
不使用代理类(With no Proxy)
在不使用代理类的时候,我们直接定义一个Car类来实现IVehicle接口
实现代码如下:
/*** Class Car*/public class Car implements IVehicle { private String name; public Car(String name) {this.name = name;} public void start() { System.out.println("Car " + name + " started"); } // stop(), forward(), reverse() implemented similarly. // getName() not shown.}
在执行时,直接调用Car类中实现的方法即可:
/*** Class Client1.* Interacts with a Car Vehicle directly.*/public class Client1 { public static void main(String[] args) { IVehicle v = new Car("Botar"); v.start(); // 通过接口变量v直接调用即可 v.forward(); v.stop(); }}
所得到的结果如下:
Car Botar started
Car Botar going forward
Car Botar stopped
使用普通的代理类(With Proxy)
- 在使用代理的方式时:
- 用一个class VehicleProxy来实现IVehicle接口,这个VehicleProxy类就是我们的代理类
- 在VehicleProxy中定义一个
private IVehicle v
来接收传进来的IVehicle c = new Car("Botar")
- 在VehicleProxy类中把IVehicle接口中的全部方法实现一遍,不用真的都重新写一遍,只要用
private IVehicle v
调用即可。像这样:
// IVehicleProxy中重写的start()方法public void start() { v.start();}
- 在主函数中调用所需方法时,不是用Car来调用,而是用代理类VehicleProxy来调用。像这样:
IVehicle c = new Car("Botar");IVehicle v = new VehicleProxy(c);v.start();
整体代码如下:
class VehicleProxy的实现:
/*** Class VehicleProxy.*/public class VehicleProxy implements IVehicle { private IVehicle v; public VehicleProxy(IVehicle v) {this.v = v;} public void start() { System.out.println("VehicleProxy: Begin of start()"); v.start(); System.out.println("VehicleProxy: End of start()"); } // stop(), forward(), reverse() implemented similarly. // getName() not shown.}
主函数:
/*** Class Client2.* Interacts with a Car Vehicle through a VehicleProxy.*/public class Client2 { public static void main(String[] args) { IVehicle c = new Car("Botar"); IVehicle v = new VehicleProxy(c); v.start(); v.forward(); v.stop(); }}
所得到的结果如下:
VehicleProxy: Begin of start()
Car Botar started
VehicleProxy: End of start()
VehicleProxy: Begin of forward()
Car Botar going forward
VehicleProxy: End of forward()
VehicleProxy: Begin of stop()
Car Botar stopped
VehicleProxy: End of stop
使用动态代理类(With Dynamic Proxy)
动态代理类特点
- 在运行中创建
- 实现了一系列接口
- 衍生出2个概念
代理接口(proxy interface):代理类所实现的接口
代理实例(proxy instance):代理类的实例
每个代理实例(proxy instance)都有一个调用处理器(invocation handler object)
代理实例的创建
- 通过
Proxy.newProxyInstance()
来创建一个代理实例
- 通过
方法说明:public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler ih) throws IllegalArgumentException参数说明:ClassLoader loader: 类加载器,可以通过如下方法获得:ClassLoader cl = 要代理的接口.class.getClassLoader();Class[] interfaces: 每个元素都是代理类要实现的接口InvocationHandler ih: 调用处理器
- 通过创建代理实例的参数可知,每个代理实例都有一个调用处理器
- 当一个代理实例调用一个方法时:
- First,对这个调用方法进行编码
- Next,调用调用处理器中的invoke()方法
invoke()方法说明:public Object invoke(Object proxy, Method method,Object[] args) throws Throwable参数说明:Object proxy: 调用这个方法的代理实例Method method: 与代理实例所调用的接口方法相符合的方法Object[] args: 一个包含上述方法的所有参数的值的数组
整体代码如下:
调用处理器部分:
import java.lang.reflect.*;/*** Class VehicleHandler.*/public class VehicleHandler implements InvocationHandler { private IVehicle v; public VehicleHandler(IVehicle v) {this.v = v;} public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { System.out.println("Vehicle Handler: Invoking " + m.getName()); return m.invoke(v, args); }}
主函数:
import java.lang.reflect.*;/*** Class Client3.* Interacts with a Car Vehicle through a dynamically* generated VehicleProxy.*/public class Client3 { public static void main(String[] args) { IVehicle c = new Car("Botar"); ClassLoader cl = IVehicle.class.getClassLoader(); IVehicle v = (IVehicle) Proxy.newProxyInstance(cl, new Class[] {IVehicle.class}, new VehicleHandler(c)); v.start(); v.forward(); v.stop(); }}
所得到的结果如下:
Vehicle Handler: Invoking start
Car Botar started
Vehicle Handler: Invoking forward
Car Botar going forward
Vehicle Handler: Invoking stop
Car Botar stopped
使用动态代理的原因
- 普通的代理类有如下2个缺点:(观察使用普通的代理类的例子即可发现)
- 不得不在代理类VehicleProxy中实现IVehicle接口中的全部方法,这比较麻烦
- 代理类VehicleProxy只能代理IVehicle这一种接口,要想代理别的接口,需要写另外一个代理类
而使用动态代理则可以很好的解决上述2个问题!!!
对于动态代理:
- 要用到需要代理的接口中的哪个方法就只代理哪个方法即可,无需实现所有要代理的接口中的全部方法
- 可以代理任何接口
- Java中的代理(Proxies in Java)
- Java语言动态代理(Dynamic Proxies)实例
- Java Networking and Proxies(译文)
- Java Networking and Proxies
- Java networking and proxies
- Java Proxies and UndeclaredThrowableException
- Java Reflection - Dynamic Proxies
- 代理proxies
- Java Notes-15(Proxies, RIM)
- 代理(Proxy) in Java
- 深入浅出ES6(十二):代理 Proxies
- 深入浅出ES6(十二):代理 Proxies
- Java中的代理(Proxy)
- Java validation with dynamic proxies(IBM)
- Java 代理模式(二) Java中的动态代理
- Java中的代理模式
- JAVA中的代理技术
- Java中的代理模式
- 【JS】幻灯片
- C++快速温习笔记(高级)[1]
- 使用C语言访问MySQL数据库
- Spring MVC 菜鸟教程 5 DispatcherServlet执行流程涉及处理类
- opencv学习之寻找凸包,使用多边形包围轮廓
- Java中的代理(Proxies in Java)
- 【黑苹果教程】ELAN,FocalTech 以及 Synaptics 触控板驱动
- 【UOJ#34】 多项式乘法(FFT && NTT)
- 用myeclipse创建maven项目时,生成的项目名中总是包含Maven Webapp的问题
- Spring MVC 菜鸟教程 6 GET,POST,PUT,DELETE
- 简单几句CSS代码,就可以把网站变成黑白色
- ==和equals方法的区别
- flask扩展模块flask-sqlachemy 的使用---mysql数据库
- Levenshtein算法