石建 | Fat Mind

Proxy学习

题记:很长都没有学到这个时间啦,怀念大三。

一、摘要

1.       什么是“代理”

2.       代理模式与适配器模式、装饰者模式的区别,适用场景

3.       手工代理

4.       动态代理的原理

 

二、什么是“代理”

       如:一个CEO,会有一个助理,任何需要CEO处理的事情,都会经过助理过滤、整理后交给CEO。助理就是CEO的代理。

       自己理解,代理就是为帮实际的执行者,做数据的过滤和控制,为实际执行者屏蔽掉外部其它因素的影响,专心去做应该做的事情。

 

三、代理模式与适配器模式、装饰者模式的区别,适用场景

1、代理模式

HeadFirst 定义:为另一个对象提供一个替身或占位符以控制对这个对象的访问。


如上图,代理模式的结构。

适用的场景,如:远程访问、访问权限控制、日志记录等。

装饰者模式,IO类图结构如下:



可以从OutputStream à FileOutputStream à BufferedOutputStream,功能依次增强,为对象增加更多的行为。

自己理解:目的不一样,代理是为控制对被代理对象的访问;装饰者,是对被装饰者功能的增强,避免过度使用继承实现不同的功能。

 

适配器模式,其区别从类图即可分辨出来,如下



Client请求ExecuteClass,但ExecuteClass暴露的接口不符合client的要求,在双方系统都不修改的情况下,利用适配器模式解决此问题。

三、手工代理



场景:根据id,获取Item;代理检查用户的权限是否有权限查看Item,已经记录log日志。具体代码很容易实现。

四、动态代理

对上面的场景,如果使用动态代理,步骤:

1. 根据interface,通过loader,生成Class对象

Class clazz = Proxy.getProxyClass(ItemService.class.getClassLoader(), ItemService.class);

2. 通过反射,获取Class对象的Construct对象(注意:Construct对象需要的参数类型)

Constructor c = clazz.getConstructor(InvocationHandler.class);

3. 调用Construct对象 newInstance()生成实例对象

proxy = (ItemService)c.newInstance(this); //thisInvocationHandler实例

 

思考问题:实现原理是什么



 

对于上面场景,实际动态生成的代理的类图。对代理的任何调用都会,super.handle.invoke(),用户实现InvocationHandler,覆写invoke方法,实现基于方法的控制。

从类图,也解释了为什么只能实现“接口”的动态代理,因为代理本身需要继承Proxy,如果实现“类”的代理,意味着要同时继承两个类,与Java不支持多继承相违背。

附代码是从网上摘抄过来的,代理的源码:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Manager {
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;

static {
   
try {
    m1 = Class.forName("java.lang.Object").getMethod("equals",
      
new Class[] { Class.forName("java.lang.Object") });
    m0 = Class.forName("java.lang.Object").getMethod("hashCode",
      
new Class[0]);
    m3 = Class.forName("com.ml.test.Manager").getMethod("modify",
      
new Class[0]);
    m2 = Class.forName("java.lang.Object").getMethod("toString",
      
new Class[0]);
   } catch (NoSuchMethodException nosuchmethodexception) {
    
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
   } catch (ClassNotFoundException classnotfoundexception) {
    
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
   }
}

public $Proxy0(InvocationHandler invocationhandler) {
   
super(invocationhandler);
}
@Override
public final boolean equals(Object obj) {
   
try {
    
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
      .booleanValue();
   } catch (Throwable throwable) {
    
throw new UndeclaredThrowableException(throwable);
   }
}
@Override
public final int hashCode() {
   
try {
    
return ((Integer) super.h.invoke(this, m0, null)).intValue();
   } catch (Throwable throwable) {
    
throw new UndeclaredThrowableException(throwable);
   }
}
}


posted on 2010-12-12 02:24 石建 | Fat Mind 阅读(217) 评论(0)  编辑  收藏 所属分类: 一点理解


只有注册用户登录后才能发表评论。


网站导航:
 

导航

<2010年12月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

统计

常用链接

留言簿

随笔分类

随笔档案

搜索

最新评论

What 、How、Why,从细节中寻找不断的成长点