




已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1. 代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 代理模式一般涉及到的角色有: 抽象角色:声明真实对象和代理对象的共同接口; 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献1) 以下以Java与模式中的示例为例: 抽象角色: abstract public class Subject /生产商 abstract public void request(); /生产手机 真实角色:实现了Subject的request()方法。 public class RealSubject extends Subject public RealSubject() public void request() System.out.println(From real subject.); 代理角色: public class ProxySubject extends Subject private RealSubject realSubject; /以真实角色作为代理角色的属性 public ProxySubject() public void request() /该方法封装了真实对象的request方法 preRequest(); if( realSubject = null ) realSubject = new RealSubject(); realSubject.request(); /此处执行真实对象的request方法 postRequest(); private void preRequest() /something you want to do before requesting private void postRequest() /something you want to do after requesting 客户端调用: Subject sub=new ProxySubject(); Sub.request(); 由以上代码可以看出,客户实际需要调用的是RealSubject类的request()方法,现在用ProxySubject来代理RealSubject类,同样达到目的,同时还封装了其他方法(preRequest(),postRequest(),可以处理一些其他问题。 另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。欢迎光临学网,收藏本篇文章 1 2 3$False$2.动态代理类 Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类: (1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。 (2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容: Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。 Static Class getProxyClass (ClassLoader loader, Class interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。 Static Object newProxyInstance(ClassLoader loader, Class interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。 所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。(参见文献3) 在使用动态代理类时,我们必须实现InvocationHandler接口,以第一节中的示例为例: 抽象角色(之前是抽象类,此处应改为接口): public interface Subject abstract public void request(); 具体角色RealSubject:同上; 代理角色: import java.lang.reflect.Method; import java.lang.reflect.InvocationHandler; public class DynamicSubject implements InvocationHandler private Object sub; public DynamicSubject() public DynamicSubject(Object obj) sub = obj; public Object invoke(Object proxy, Method method, Object args) throws Throwable System.out.println(before calling + method); method.invoke(sub,args); System.out.println(after calling + method); return null; 该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;此外,在该类还实现了invoke方法,该方法中的 method.invoke(sub,args); 其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,args为执行被代理对象相应操作所需的参数。通过动态代理类,我们可以在调用之前或之后执行一些相关操作。欢迎光临学网,收藏本篇文章 1 2 3客户端: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class Client static public void main(String args) throws Throwable RealSubject rs = new RealSubject(); /在这里指定被代理类 InvocationHandler ds = new DynamicSubject(rs); /初始化代理类 Class cls = rs.getClass(); /以下是分解步骤 /* Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces() ; Constructor ct=c.getConstructor(new ClassInvocationHandler.class); Subject subject =(Subject) ct.newInstance(new Objectds); */ /以下是一次性生成 Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds ); subject.request(); 通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系(参见文献2)。 在目前的Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。 其实现主要通过是java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。 Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现,如下,HelloWorld接口定义的业务方法,HelloWorldImpl是HelloWorld接口的实现,HelloWorldHandler是 InvocationHandler接口实现。代码如下: 业务接口: public interface HelloWorld void sayHelloWorld() ; 业务接口实现: public class HelloWorldImpl implements HelloWorld public void sayHelloWorld() System.out.println(Hello World!); InvocationHandler实现,需要在接口方法调用前后加入一部份处理工作,这里仅仅在方法调用前后向后台输出两句字符串,其代码如下: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class HelloWorldHandler implements InvocationHandler /要代理的原始对象 private Object objOriginal; /* * 构造函数。 * param obj 要代理的原始对象。 */ public HelloWorldHandler(Object obj) this.objOriginal = obj ; public Object invoke(Object proxy, Method method, Object args) throws Throwable Object result ; /方法调用之前 doBefore(); /调用原始对象的方法 result = method.invoke(this.objOriginal ,args); /方法调用之后 doAfter(); return result ; private void doBefore() System.out.println(before method invoke!); private void doAfter() System.out.println(after method invoke!); 测试代码: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class Test public static void main(String args) HelloWorld hw = new HelloWorldImpl(); InvocationHandler handler = new HelloWorldHandler(hw); HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance( hw.getClass().getClassLoader(), hw.getClass().getInterfaces(), handler); proxy.sayHelloWorld(); 首先获取一个业务接口的实现对象; 获取一个InvocationHandler实现,此处是HelloWorldHandler对象; 创建动态代理对象; 通过动态代理对象调用sayHelloWorld()方法,此时会在原始对象HelloWorldImpl. sayHelloWorld()方法前后输出两句字符串。 运行测试类输出如下: before method invoke! Hello World! after method invoke! 此处Test类中的方法调用代码比较多,在我们的实际应用中可以通过配置文件来来简化客户端的调用实现。另外也可以通过动态代理来实现简单的AOP。Java中代理模式(Proxy)的认识。 代理,想必大家都应该知道是什么冬冬了,一般的手机产商都有代理商,歌星们都有自己的经纪人,如此这些都可以看作是一种代理模式。下面我选择如下的一种情景来进行讲述:某董事长出差,但是此时公司有个聚会,董事长买单,但是由他的秘书去结帐。我们就权且把这个看作一个代理行为,_。 首先我们定义一个接口:商人(Merchant),如下所示: .hust.cm.test; publicinterfaceMerchant voidtreat();/商人都要请客吃饭滴,_ 然后我们定义一个类:董事长(Director),如下所示: .hust.cm.test; publicclassDirectorimplementsMerchant publicDirector() publicvoidtreat() System.out.println(董事长请大家吃饭); OK,我们现在要给他找代理了,这个代理就是他的秘书(Secretary)。这里要涉及到一些代理的机制了。在Java中,用来做代理的类一般都要实现InvocationHandler,实现它的invoke方法,至于为啥是这样俺也不知道了,_。另外,当我们产生一个代理实例(proxyinstance)的时候,只要我们通过这个实例调用任何方法,都会导致invoke方法的调用,还是看例子吧,如下所示: .hust.cm.test; importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Method; publicclassSecretaryimplementsInvocationHandler publicSecretary(Directordirector) this.director=director; publicObjectinvoke(Objectarg0,Methodarg1,Objectarg2) throwsThrowable director.treat(); System.out.println(由秘书结帐咯!); returnnull; privateDirectordirector; 现在我们开始构建我们的主体测试代码,如下面的代码所示: .hust.cm.test; importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.P
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年建筑施工安全管理信息化在工程项目中的应用案例分析
- 2025年婴幼儿配方食品营养配方优化对婴幼儿视力发育的影响研究
- 2025年城市轨道交通智慧运维系统建设与智能运维管理优化策略深度报告
- 轻化工专业试题及答案解析
- 2025年塔吊维修证考试题及答案
- DB65T 4404-2021 植保无人飞机防治棉花病虫害作业规程
- 敬业专业实践面试题及答案
- 2025年新能源行业企业绿色建筑技术应用与效果分析报告
- 电厂防雷应急预案(3篇)
- 低温工作应急预案(3篇)
- 教师网络安全培训内容
- 养老护理员礼仪
- 护理疑难病例讨论肺心病
- 真石漆施工质量缺陷分析与防治
- 《朊病毒及其检测》课件
- 中学副校长培训方案
- 砌体工程质量控制培训课件
- 无人机测试评分标准
- 沟通技巧培训课件(共66张PPT)
- GB/T 42538.1-2023农林拖拉机安全第1部分: 基本型拖拉机
- 胡寿松《自动控制原理》(第6版)笔记和课后习题(含考研真题)
评论
0/150
提交评论