- 浏览: 888769 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
小宇宙_WZY:
膜拜一下大神,解决了我一个大问题,非常感谢 orz
【解惑】深入jar包:从jar包中读取资源文件 -
JKL852qaz:
感谢,遇到相同的问题!
【解惑】深入jar包:从jar包中读取资源文件 -
lgh1992314:
为什么java中调用final方法是用invokevirtua ...
【解惑】Java动态绑定机制的内幕 -
鲁曼1991:
说的都有道理,protected只能被同一级包的类所调用
【解惑】真正理解了protected的作用范围 -
鲁曼1991:
...
【总结】String in Java
代理(Proxy)实际上是一种设计模式。代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
//抽象角色: public interface Subject{ void request(); } //真实角色:实现了Subject的request()方法。 public class RealSubject implements Subject{ public void request() { System.out.println("我是真是角色"); } } //代理角色: public class ProxySubject implements Subject{ //以真实角色作为代理角色的属性 private RealSubject realSubject; public ProxySubject(RealSubject real){ this.realSubject=real; } //该方法改变了真是对象的request行为 public void request(){ System.out.println("之前设置新行为" ); realSubject.request(); //此处执行真实对象的request方法 System.out.println("之后设置新行为" ); } } //main测试 Subject sub=new ProxySubject(); Sub.request();
从上面的代码可以看出,我们可以通过建立代理角色ProxySubject来改变真实角色中的request方法功能(在原方法前后添加些功能)。这个应用非常的广泛,大家可以想想Struts2框架中拦截器在Action执行前所做的工作。但事实上Struts2框架是如何做到这一点的却是十分的复杂,我们需要往下看。
我们进一步想一下,当我们知道了抽象角色Subject的具体定义(request方法)的时候,我们当然可以很方便的通过包装Subject的真实角色RealSubject来定义一个能够部分改变真实角色行为的代理角色ProxySubject。但是很多情况下,我们事先并不知道需要代理的对象到底是什么类型的。或者说,只有在运行过程中才知道具体的对象。那么我们能否定义
一种具体行为的代理类,能够动态的实例化任何类型的代理对象呢?说白了,我们就是想做到下面这件事:
定义一种具体行为的代理类型:
public class ProxySubject implements interfaceX{
private ClassX obj;
public ProxySubject(ClassX obj){
this.obj=obj;
}
public void methodX(){
....新增行为
obj.methodx();//真实对象行为
....新增行为
}
}
运行时遇到不同类型的对象,都能够使用ProxySubject代理来完成新的行为:
ClassA oa=....
new ProxySubject(oa).methodX;
ClassA ob=....
new ProxySubject(oa).methodX;
做到这一点是很困难的,但并非不可能,Java的代理机制就能够帮助我们完成这件事。
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
(1) InvocationHandler接口,是代理实例的调用处理程序实现的接口。 它只有一个方法:invoke(Object proxy, Method method, Object[] args)。我们需要在实现InvocationHandler接口的具体类中的invoke方法内,编写代理行为的具体逻辑。然后将这个InvocationHandler对象传递给Proxy类中生成一个动态的代理对象。
(2) Proxy 类,提供用于创建动态代理类和实例的静态方法。其最重要的两个静态创建方法:
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
以上面的代码为例,编写一个动态代理类:
//完成代理行为 import java.lang.reflect.Method; import java.lang.reflect.InvocationHandler; public class DynamicSubject implements InvocationHandler { private Object sub; //被代理类 public DynamicSubject(Object obj) { sub = obj; } //无论何时调用代理类的方法,都会执行这个invoke方法的。 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用被代理对象的方法是:"+method.getName()+" "+method.getDeclaringClass()); System.out.println("之前设置新行为" ); method.invoke(sub,args); //动态调用被代理类的行为方法。 System.out.println("之后设置新行为" ); return null; } } //测试 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.io.*; static public void main(String[] args) throws Throwable{ Object real=new RealSubject(); //被代理对象 InvocationHandler handler = new DynamicSubject(real); //生成一个具体的代理行为 Object proxyed = Proxy.newProxyInstance(real.getClass().getClassLoader(), real.getClass().getInterfaces(),handler); //动态生成实现Subject接口的代理类 对象 if(proxyed instanceof Subject){ Subject subProx=(Subject)proxyed; subProx.request(); } else proxyed.toString(); } /* 调用被代理对象的方法是:request interface hr.login.Subject 之前设置新行为 我是真是角色 之后设置新行为 */
评论
发表评论
-
NIO
2010-08-05 10:36 0在JDK1.4以前,I/O输入输出处理,我们把它称为旧 ... -
【总结】Java线程同步机制深刻阐述
2010-05-16 10:21 5937全文转载:http://www.iteye ... -
【JDK优化】java.util.Arrays的排序研究
2010-05-12 21:06 9116作者题记:JDK中有很多算法具有优化的闪光点,值得好好研究。 ... -
【JDK优化】 Integer 自动打包机制的优化
2010-03-12 19:14 4087我们首先来看一段代码: Integer i=100; In ... -
【总结】Java与字符编码问题详谈
2009-12-30 09:11 9351一、字符集和字符编码方式 计算机只懂得0/1两种信号 ... -
【解惑】 正确理解线程等待和释放(wait/notify)
2009-12-29 13:40 19662对于初学者来说,下面这个例子是一个非常常见的错误。 /** ... -
【解惑】JVM如何理解Java泛型类
2009-12-16 11:08 12235//泛型代码 public class Pair<T& ... -
【解惑】正确的理解this 和 super
2009-12-05 09:46 4419转载: 《无聊 ... -
【解惑】真正理解了protected的作用范围
2009-11-21 18:00 5009一提到访问控 ... -
【总结】String in Java
2009-11-21 17:52 10822作者:每次上网冲杯Java时,都能看到关于String无休无止 ... -
【解惑】真正理解了protected的作用范围
2009-11-16 17:11 585一提到访问控制符protected,即使是初学者 ... -
总结Java标准类库中类型相互转化的方法
2009-11-09 21:57 210组一: ☆ String → byte[ ... -
方法没覆盖住带来的烦恼
2009-11-05 09:18 100Object类是所有类的祖宗,它的equals方法比较的 ... -
【解惑】数组向上转型的陷阱
2009-11-03 11:44 1841问题提出: 有两个类Manager和Em ... -
【总结】java命令解析以及编译器,虚拟机如何定位类
2009-11-01 16:25 5755学Java有些日子了,一直都使用IDE来写程序。这 ... -
【解惑】剖析float型的内存存储和精度丢失问题
2009-10-26 15:10 15838问题提出:12.0f-11.9f=0.10 ... -
【解惑】领略内部类的“内部”
2009-10-19 15:38 3542内部类有两种情况: (1) 在类中定义一个类(私有内部类 ... -
【解惑】深入jar包:从jar包中读取资源文件
2009-10-08 21:13 65467我们常常在代码中读取一些资源文件(比如图片,音乐,文 ... -
【解惑】理解java枚举类型
2009-09-26 09:37 3360枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字e ... -
编写自己的equals方法
2009-09-20 14:18 129在我的《令人头疼的"相等"关 ...
相关推荐
java解惑java解惑java解惑java解惑java解惑java解惑
Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑
JAVA解惑,你面包括一些java经典的问题。
Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑
Java解惑中文版 Java解惑 java健壮程序
Java解惑.pdf Java解惑.pdf Java解惑.pdf Java解惑.pdf
《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》
Java解惑 Java解惑 Java解惑
JAVA解惑.pdf JAVA解惑.pdf JAVA解惑.pdf
java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑 java 解惑
与java相关的的学习,适合初学者,可以看看
讲述如何在程序中避免程序缺陷和程序陷阱的,解惑的过程中,介绍了一些Java编程语言中许多不易被掌握的知识点,其阅读价值非常高,适合具有Java知识的学习者和有编程经验的Java程序员阅读。
Java解惑,是一本以大量java实例,讲述如何在程序中避免程序缺陷和程序陷阱的,解惑的过程中,介绍了一些Java编程语言中许多不易被掌握的知识点,其阅读价值非常高,适合具有Java知识的学习者和有编程经验的Java...
JAVA面试题解惑系列合集 JAVA面试题解惑系列合集 JAVA面试题解惑系列合集
"java解惑" PDF版本
《Java解惑》 布洛克 著;陈昊鹏 译 扫描清晰带目录,仅供参阅,请支持正版
该书特写了95个有关Java或其类库的陷阱和缺陷的谜题,其中大多数谜题都采用了短程序的方式,这些程序的行为与其看似的大相径庭。在每个谜题之后都给出了详细的解惑方案,这些解惑方案超越了对程序行为的简单解释,向...
java解惑java解惑.docjava解惑.doc
JAVA解惑