当前位置:首页 > CN2资讯 > 正文内容

java代理模式及动态代理类

1天前CN2资讯

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的动态代理类来解决。

 

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为执行被代理对象相应操作所需的参数。通过动态代理类,我们可以在调用之前或之后执行一些相关操作。

客户端

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 Class[]{InvocationHandler.class}); Subject subject =(Subject) ct.newInstance(new Object[]{ds}); */ //以下是一次性生成 Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds ); subject.request(); }

       通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系(参见文献2)。

 

 

参考文献:

1.      阎宏,《Java 与模式》

2.          透明,《动态代理的前世今生》

3.   Forest Hou,《Dynamic Proxy 在 Java RMI 中的应用》



    你可能想看:

    扫描二维码推送至手机访问。

    版权声明:本文由皇冠云发布,如需转载请注明出处。

    本文链接:https://www.idchg.com/info/24167.html

    分享给朋友:

    “java代理模式及动态代理类” 的相关文章

    全球主机交流论坛:提升技术的最佳平台

    全球主机论坛概述 在当今数字化时代,全球主机论坛扮演着越来越重要的角色。这些论坛不仅是技术爱好者的聚集地,更是为需要域名、主机、VPS和服务器信息的用户提供了一个交流的平台。我作为一名站长,经常在这样的论坛上交流经验、获取灵感和解决技术难题,论坛的存在极大地丰富了我的网络建设之旅。 主机论坛的定义其...

    国外CDN推荐:提升网站速度与安全的选择

    在这个数字化时代,CDN(内容分发网络)的重要性逐渐凸显。许多网站为了提高用户体验,确保内容能够快速、安全地到达用户的设备,纷纷开始引入CDN服务。那么,CDN到底是什么?它的功能和运作原理又是怎样的呢? 简单来说,CDN是一个分布式的网络,旨在提高网站的加载速度和可用性。它通过在全球范围内部署一系...

    如何选择国内免费服务器?全面指南与推荐

    国内免费服务器概述 在当今数字化快速发展的时代,云计算的普及正以前所未有的速度改变着我们的工作和生活方式。国内云服务器市场也随着这股潮流不断壮大,越来越多的云服务提供商进入市场,尝试用优惠的价格吸引用户。尤其是对于那些刚起步的开发者和小型企业而言,国内免费服务器的出现无疑为他们提供了一个很好的机会。...

    续费同价服务器:云服务的透明定价策略与用户优势

    续费同价服务器是什么呢?说白了,就是云服务提供商在定价上采取的一种政策。无论是新用户第一次购买,还是老用户续费,价格都是一样的。这种做法让很多用户感到安心,不用担心下次续费时价格会大幅上涨。这一策略在云服务行业越来越受到重视,也给用户带来了不少好处。 首先,续费同价服务器让价格变得透明。我之前在选择...

    PumpCloud VPS主机服务解析:注册、设置与价格一站式指南

    PumpCloud是一家自2015年成立以来便致力于提供高效主机服务的公司,让我来分享下其中的一些亮点。它主要在香港和台湾设有数据中心,专注于为用户提供动态VPS服务。相比于国内一些主机商,PumpCloud显得更国际化,主要通过其快速的网络连接和强大的服务基础设施吸引用户。虽然在行业中还算年轻,但...

    波测评分析及其在医疗与教育领域的重要性

    波测评的定义与重要性 波测评是一种重要的技术手段,专注于评估波动的特性和行为。我发现,这种测评方法在多个行业中都扮演了至关重要的角色,比如医疗、工业和电力等领域。以脑波测评为例,它不仅可以帮助医生了解病人的大脑状态,还能在教育领域评估学习能力。这些应用展示了波测评技术在科学与技术进步中的不可或缺性。...