代理模式

来源:互联网 发布:php mbstring 编辑:程序博客网 时间:2024/06/03 10:01
代理模式:代理模式是对象的结构模式,代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用
代理模式中角色:
抽象对象角色:声明目标对象和代理对象的共同接口,如此在任何可使用目标对象的地方均能使用代理对象
目标对象角色:定义了代理对象所代表的目标对象
代理对象角色:代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象,代理对象提供一个与目标对象相同的接口,以便在任何时候替代目标对象,代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯的将调用传递给对象。
代理的种类:
静态代理:只能提供固定的类的代理
jdk动态代理:只能代理接口,通过反射,提高了灵活性,但性能较慢
在java的java.lang.Reflect包下提供了一个Proxy类和一个InvocationHandler接口,使用这个接口和这个类可以生成jdk动态代理类或动态代理对象。
 java.lang.reflect.InvocationHandler
  被代理实例所实现的一个接口,内部只有一个invoke()方法,签名如下;
  public Object invoke(Object proxy, Method method, Object[] args)
  当代理的方法被调用的时候,代理就会把这个调用转发给InvocationHandler,也就会调用它的invoke()方法。


Proxy提供了用于动态创建代理类和代理对象的静态方法,它也是所有动态代理类的父类,如果在程序中为一个或多个接口动态的生成实现类,就可使用Proxy类创建动态代理类;如果需要为一个或多个接口动态的创建实例,也可使用Proxy来创建动态代理实例。
Proxy提供了如下两个方法来创建动态代理类和动态代理实例。
---static Class<?> getProxyClass(ClassLoader loader,Class<?> ....interfaces)创建一个动态代理类所对应的class对象
---static Object newProxyInstance(ClassLoader loader,Class<?>[] ...interfaces, InvocationHandler h)直接创建一个动态代理对象
ClassLoader loader:类加载器 
Class<?>[] interfaces:得到全部的接口 
InvocationHandler h:得到InvocationHandler接口的子类实例 


Ps:类加载器 
在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器; 
Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的; 
Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类; 
AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。 
BookFacade book = new BookFacadeImpl();
// 创建一个InvocationHandler对象
InvocationHandler handler = new BookFacadeProxy(book);
// 使用Proxy生成一个动态代理类ProxyClass
Class proxyClass = Proxy.getProxyClass(
BookFacade.class.getClassLoader(),
new Class[] { BookFacade.class });
// 获取proxyClass类中带一个InvocationHandler参数的构造器
Constructor ctor;
try {
ctor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
BookFacade f = (BookFacade) ctor.newInstance(new Object[] { handler });
            f.addBook();
} catch (Exception e) {
e.printStackTrace();
}、
上述代码可简化为
/创建一个InvocationHandler对象
BookFacadeProxy proxy = new BookFacadeProxy(book);
//使用Proxy直接生成一个动态代理对象
BookFacade facade = (BookFacade) Proxy.newProxyInstance(book.getClass()
.getClassLoader(), book.getClass().getInterfaces(), proxy);
facade.addBook();
cglib代理:spring aop的默认实现,可以代理类,无需提供对应接口,通过asm字节码增强,速度要快于jdk的默认动态代理。针对类来实现代理的,其原理是对指定的目标类生成一个子类, 并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
代理的应用场景:
类似于spring aop的好处,通过代理模式,可以无侵入式的很方便的实现日志记录的功能,方法权限拦截功能,事务控制等功能。
代理模式的应用场景: 
(1)远程代理(Remote Proxy):典型的就是客户端与webservice使用的情况,客户端由于是针对OOP编程,而不是针对webservice中的方法进行编程,所以得在客户端模拟一下webservice的环境,用proxy来对webservice进行包装,这样就可以使用proxy代理类来远程操作webservice了;
(2)虚拟代理(Virtual Proxy):比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用proxy来进行大图片的打开;
(3)防火墙代理(Firewall Proxy):控制网络资源的访问,保护主题免于恶意客户的侵害;
(4)保护代理(Protection (Access)Proxy):为不同的客户提供不同级别的目标对象访问权限;
(5)智缓存代理(Cache Proxy):为开销大的运算结果提供暂时存储,它允许多个客户共享结果,以减少计算或网络延迟;
(6)同步代理(SynchronizationProxy):在多线程的情况下为主题提供安全的访问;
(7)写入时复制代理(Copy-On-Write Proxy):用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止,是虚拟代理的一个变体;
(8)智能引用代理(Smart ReferenceProxy):当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等;
(9)复杂隐藏代理(Complexity HidingProxy):用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也称为外观代理(Façade Proxy),但是复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。


现实中,Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用
0 0