设计模式—静态代理模式和动态代理模式(Proxy Pattern)
2015-08-20 18:09
585 查看
一、静态代理模式
代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。—《Head First设计模式 》书中对代理模式的定义。打个比方说,你要买火车票,但是你又不想去很远的火车站去买,所以你会选择去附近的代售点去买,但是,你要知道代售点并不是自己买票,只有火车站才真正卖票,代售点卖给你的票其实是通过火车站实现的。代理模式有三个组成部分:
(1)抽象角色:通过接口或抽象类声明真实角色实现的业务方法;
(2)代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作;
(3)真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
代理模式UML图如下:
接下来,我们来看一个示例:
抽象角色:
package com.proxy01; //抽象角色 public interface Subject { void request(); }
真实角色:
package com.proxy01; //真实角色 public class RealSubject implements Subject { @Override public void request() { System.out.println("From real subject"); } }
代理角色:
package com.proxy01; public class ProxySubject implements Subject { // 以真实角色作为代理角色的属性 private Subject realSubject; public ProxySubject(Subject realSubject) {this.realSubject = realSubject ;} // 该方法封装了真实对象的request方法 public void request() { preRequest(); realSubject.request(); // 此处执行真实对象的request方法 postRequest(); } private static void preRequest(){ System.out.println("前置处理"); } private static void postRequest(){ System.out.println("后置处理"); } }
客户端:
package com.proxy01; public class Client { public static void main(String[] args) { RealSubject real = new RealSubject(); Subject sub = new ProxySubject(real); sub.request(); } }
运行结果:
前置处理 From real subject 后置处理
以上介绍的是静态代理模式,静态代理在程序运行之前,代理类的.class文件就已经存在了。而接下来要介绍的动态代理模式在程序运行时,运用反射机制动态创建而成。
二、Java中的动态代理模式
从JDK1.3开始,java中引入了动态代理机制。动态代理有两部分组成,分别是:(1)代理接口,是代理类实现的一个接口。
(2)代理实例,是代理类的一个实例。
相关的接口或类有如下两个:InvocationHandler和Proxy,都位于java.lang.reflect包下。
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的
invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
其中:
Object proxy:指代我们代理那个真实对象;
Method method:指代的是我们所要调用真实对象的某个方法的Method对象 ;
Object[] args:方法调用时所需要的参数 。
接下来我们来看看Proxy类,Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了好多方法,但是我们用的最多的就是 newProxyInstance这个方法
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException其中:
loader:一个ClassLoder 对象,定义了由哪个ClassLoder 对象来对生成的代理进行加载;
interface:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一个接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了;
h:一个Invocationhandler对象,表示的是当我这个动态代理对象在调用方法 的时候,会关联到哪一个Invocationhandler对象上。
动态代理UML图如下:
此图来源于:http://www.cnblogs.com/machine/archive/2013/02/21/2921345.html
同样,我们来实现一个简单实例
抽象角色:
package com.proxy; //抽象角色 public interface Subject { void request(); }具体角色:
package com.proxy; //具体角色 public class RealSubject implements Subject { @Override public void request() { System.out.println("From real subject"); } }代理处理器:
package com.proxy; //代理处理器 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynamicSubject implements InvocationHandler { private Object sub; public DynamicSubject() {} public DynamicSubject(Object sub) { super(); this.sub = sub; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("前置处理"); method.invoke(sub, args); System.out.println("后置处理"); return null; } }客户端:
package com.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) throws Throwable{ RealSubject rs=new RealSubject(); InvocationHandler ds=new DynamicSubject(rs); Class cls=rs.getClass(); Subject subject=(Subject)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), ds); subject.request(); } }运行结果:
前置处理 From real subject 后置处理参考:java的动态代理机制详解
java代理机制
相关文章推荐
- C++友元类【未完待续】
- C# 反射机制
- CodeForces 553A Kyoya and Colored Balls (排列组合)
- 百度地图Javascript SDK
- 版本控制 - Git
- 多态与反射的例子
- java annotation处理器
- 使用Excel批量生成SQL脚本(小技巧)
- OpenCV2中滑动条(Trackbar)回调函数的小发现
- highstock-处理时间需要处理世界时间偏移量
- drupal_get_css -- drupal
- mongodb命令使用大全(常用命令)
- Unity3D开发——LeRunning角色选择界面制作
- 9.11排序与查找(三)——给定一个排序后的数组,包含n个整数,但这个数组已被旋转过多次,找出数组中的某个元素
- js 类引用方式的区别
- java thread cpu
- UNIX Tutorial Eight
- Java系列笔记(1) - Java 类加载与初始化
- 树莓派做web服务器(nginx、Apache)
- 154. Factorial (二分+数论)