代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。
在面向对象编程中,直接引用某些对象会因为种种原因(比如对象创建的开销过大,访问需要安全控制,或者需要跳出当前进程等)带来很多问题,给用户或者系统本身带来不便或者异常。这时,就需要在操作对象(客户端)和被调用对象(真实对象)之间添加一个代理,以协助操作对象控制对被调用对象的访问,起到透明中介的作用。
代理模式的应用:一是远程代理,即为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实;二是虚拟代理,即根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象;三是安全代理,用来控制真实对象访问时的权限;四是智能指引,即当调用真实对象时,代理处理另外一些事。
代理模式的实现,主要有以下几个特点:
1.真实对象和代理对象拥有共同的父类或者实现相同的接口,实现了相同的方法;
2.代理对象引用或者包含真实对象的一个实例,该实例在代理对象中初始化,代理对象通过1中所述的相同方法来替代对真实对象的调用;
3.客户端中不再实例化真实对象,完全通过代理对象来访问真实对象。
代理模式的简单示例,参见如下地址:
http://www.cnblogs.com/kid-li/archive/2006/10/18/532192.html
顺带一提的是,百度百科“java代理模式”词条中的代码示例实际上是装饰模式,而不是代理模式。
在Java中,通常使用Proxy(动态代理)来实现对代理模式的支持。动态代理的详细描述参见《Java核心技术(卷1)》6.5节·代理。
Java中要创建一个代理对象,必须调用Proxy类的静态方法newProxyInstance,该方法的原型如下:
Object Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws IllegalArgumentException
其中:
loader,表示类加载器,对于不同来源(系统库或网络等)的类需要不同的类加载器来加载,这是Java安全模型的一部分。可以使用null来使用默认的加载器;
interfaces,表示接口或对象的数组,它就是前述代理对象和真实对象都必须共有的父类或者接口;
handler,表示调用处理器,它必须是实现了InvocationHandler接口的对象,其作用是定义代理对象中需要执行的具体操作。
InvocationHandler之于Proxy,就如Runnable之于Thread。InvocationHandler接口中只有一个方法invoke,它的作用就跟Runnable中的run方法类似,定义了代理对象在执行真实对象的方法时所希望执行的动作。其原型如下:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
其中:
proxy,表示执行这个方法的代理对象;
method,表示真实对象实际需要执行的方法(关于Method类参见Java的反射机制);
args,表示真实对象实际执行方法时所需的参数。
在实际的编程中,需要优先定义一个实现InvocationHandler接口的调用处理器对象,然后将它作为创建代理类实例的参数。(抑或在调用newProxyInstance方法时使用匿名内部类。)这样就得到了代理对象。
真实对象本身的实例化在调用处理器对象内部完成,实例化时需要的参数也应该及时传入调用处理器对象中。这样一来就完成了代理对象对真实对象的包装,而代理对象需要执行的额外操作也在invoke方法中处理。
其后,在客户端中,如果需要使用真实对象时,就可以用代理对象来替代它了(有时需要类型强制转化)。
下面的示例用Java的动态代理模拟了一个拦截器的功能:对于实现了Action接口的类,如果类名不以Action结尾,则不予执行。
共同接口Action:
实现了Action接口的三个真实对象:
调用处理器对象FilterHandler,它是对拦截器的实现:
客户端:
最后需要特别说明的是:
1.Proxy创建的代理对象实例包含Object类中的全部方法和接口数组(即newProxyInstance方法中的interfaces参数)中的全部方法。但是,代理类会覆盖Object类中的toString、equals和hashCode方法,而clone、getClass等方法则没有重新定义。另外,所有这些方法都需要在InvocationHandler的invoke方法中通过调用Method对象的invoke方法才能真正被执行。
2.对于特定的类加载器和预设的一组接口来说,即便是调用处理器handler不一样,也只能得到同一个代理类。也就是说,示例中三次对newProxyInstance方法的调用,其实只是得到的同一个对象的三个实例而已,并不是三种不同的类。
其它Java动态代理的细节参见《Java核心技术》或Java API。
分享到:
相关推荐
java 代理模式实现代码及设计详解:动态代理模式、静态代理模式
NULL 博文链接:https://sunlibao123.iteye.com/blog/1837500
设计模式C++学习之代理模式(Proxy)
* 动态代理中的静态方法:java.lang.reflect.Proxy.newProxyInstance (ClassLoader(类加载器),interface(接口),handler(监听处理器)) * * 代码示例:《帮爸爸买菜》 * 1.Father: 被代理类,必须需要实现接口 ...
java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...
设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...
代理模式java代码 Proxy(4) 开发宝典......
详解设计模式中的proxy代理模式及在Java程序中的实现共14页.pdf.zip
代理模式java代码 Proxy(1) java 学习必备......
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式)
用sun的JDK API实现java的动态代理类
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) (Level 300)
代理模式java代码 Proxy(5) 2个代理类 开发宝典
- 静态代理与动态代理 - 常见的动态代理实现 - JDK Proxy - CGLIB - JDK Proxy 和 CGLIB 的对比 - 动态代理的实际应用 - Spring AOP 说在前面:今天我们来聊一聊 Java 中的代理,先来聊聊故事背景: 小明想...
NULL 博文链接:https://cn-done.iteye.com/blog/1743191
Android设计模式之代理模式(Proxy Pattern)
代理模式(Proxy) 定义: 为其他对象提供一种代理以控制对这个对象的访问 结构: 由三部分组成 1.RealSubject(真实对象): 真正会调用到的对象 2.Proxy(代理对象): 代理真实对象的地方 3.Subject(共同点): 代理对象...
36种最新设计模式整理 Design Pattern: Simple Factory 模式 Design Pattern: Abstract Factory 模式 Design Pattern: Builder 模式 Design Pattern: Factory Method 模式 Design Pattern: Prototype 模式 ...
JAVA动态代理,采用Proxy与InvocationHandler实现。
Java 实现免费代理IP的获取方式 并动态实时校验是否有效,java文件项目内含有Jsoup的Jar包(Jsoup是加工过的,含请求),有2个主入口程序: 其一:用于请求代理IP,并立即校验是否是一个有效的代理IP,如果有效,...