Java设计模式之代理模式

代理模式,定义为,为另一对象提供一个占位符或者替身以控制对这个对象的访问。故代理模式核心思想就是控制对象访问。
使用代理模式创建代理,可以让代表对象控制某一个对象的访问,该被代表对象可以是远程对象,创建开销大的对象或者需要安全控制的对象。
几种常见的代理控制访问方式:
1)远程代理控制访问远程对象
2)虚拟代理控制访问创建开销大的资源
3)保护代理基于权限控制对资源的访问
代理模式的基本类图
Java设计模式之代理模式
Proxy和RealSubject都实现了共同的接口,这允许任何客户都可以像处理RealSubject一样处理Proxy
RealSubject通常是真正做事的对象,proxy会控制对RealSubject的访问。
Proxy持有Subject引用,它可以创建RealSubject对象,来将请求转发给Subject
远程代理
远程代理其实就是远程对象在本地代表,或者说是另一个jvm堆上的对象在本jvm堆中的代表。本地代表,指的就是一种可以由本地方法调用的对象,其行为会转发到远程对象中。
在利用远程代理中,客户对象操作的就是远程对象在本地的代理,客户对象所做的就像是在做远程方法调用,但其实只是调用本地堆中的“代理”对象的方法,再由该代理对象处理所有网络通信的底层细节。
为了实现远程代理,调用远程方法,一般我们就利用RMI(Remote Method Invocation),RMI可以让我们找到远程JVM内的对象,并且允许我们调用它们的方法。关于如何实现RMI的,请参见另一个博客介绍,Java远程方法调用RMI的实现
虚拟代理
虚拟代理主要是作为创建开销大的对象的代表,虚拟代理经常直到我们真正需要一个对象的时候才创建它,当对象在创建前和创建中的时候,由虚拟代理来扮演对象的替身。对象创建完后,代理就会将请求直接委托给对象。
保护代理
保护代理,就是根据访问权限决定客户是否可以访问对象的代理。
一般保护代理就是通过动态代理来实现的,现在就主要讨论一下动态代理如何实现及流程。
动态代理
Java.lang.reflect包有对于代理的支持,可以在运行的时候动态创建一个代理类,实现一个或者多个接口,并将方法的调用转发到你所指定的类。在java中创建动态代理,必须要为你要创建的类先定义一个接口。
动态代理类图如下:
Java设计模式之代理模式
动态代理过程中,是由java内置的创建一个proxy类,该类同样是实现了Subject接口,由于该代理类是由java动态创建的,不能将逻辑代码放置到Proxy类里面,则就放置到InvocationHandler中,它主要是相应代理的任何调用信息,当代理收到方法调用的时候,都是委托给InvocationHandler做的。
Proxy 的静态方法
该方法用于获取指定代理对象所关联的调用处理器 
static InvocationHandler getInvocationHandler(Object proxy) 
该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象 
static Class getProxyClass(ClassLoader loader, Class[] interfaces) 
该方法用于判断指定类对象是否是一个动态代理类 
staticboolean isProxyClass(Class cl) 
该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例 
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
InvocationHandler 的核心方法
第一个参数是代理类实例,第二个参数是被调用的方法对象,第三个方法是调用参数
调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行 
Object invoke(Object proxy, Method method, Object[] args)
使用 Java 动态代理的具体步骤:
1. 通过实现 InvocationHandler 接口创建自己的调用处理器,并且提供一个方法设置代理类
2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
动态代理创建实例代码
基类接口
package imitate.proxy.intercepter;
publicinterface Dog {
void info();
void run();
}
被代理实现类
package imitate.proxy.intercepter;
publicclass DogImpl implements Dog{
@Override
publicvoid info() {
// TODO Auto-generated method stub
System.out.println("可爱的小猎狗");
}
@Override
publicvoid run() {
// TODO Auto-generated method stub
System.out.println("疯狂的跑呀跑呀");
}
}
生成代理的类
package imitate.proxy.intercepter;
import java.lang.reflect.Proxy;
//根据目标对象生成一个代理对象
publicclass MyProxyFactory {

publicstatic Object getProxy(Object obj)
{
//代理的处理类
ProxyHandler proxy=new ProxyHandler();
proxy.setTarget(obj);
//第一个参数用来创建动态代理的对象
//第二个参数代理的接口对象数组
//第三个参数代理包含的处理实例
//返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于: 
return Proxy.newProxyInstance(obj.getClass.getClassLoader(),
obj.getClass().getInterfaces(), proxy);
}
}
代理调用处理器接口
package imitate.proxy.intercepter;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

publicclass ProxyHandler implements InvocationHandler {

//需要被代理的目标对象
private Object target;
//用于设置传入目标对象的方法
publicvoid setTarget(Object obj)
{
this.target=obj;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object result=null;
if(method.getName().equals("info"))
{
System.out.println("First enter here");
result=method.invoke(target, args);
System.out.println("Last exit here");
}
else
{
System.out.println("First other enter here");
result=method.invoke(target, args);
System.out.println("First other enter here");
}
return result;
}

}
动态代理测试类
package imitate.proxy.intercepter;

publicclass TestDog {
publicstaticvoid main(String[] args) {

Dog target=new DogImpl();
Dog dog=null;
//以目标对象创建代理
Object proxy=MyProxyFactory.getProxy(target);
if(proxy instanceof Dog)
{
dog=(Dog)proxy;
}
dog.info();
}
}


本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1178054

上一篇:java设计模式学习(-)


下一篇:Java设计模式之状态模式