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

【设计模式】代理模式设计模式 代理

9小时前CN2资讯

代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问,因为在某些情形下,我们不能直接或不方便直接访问某些类,或者我们需要对访问的类做一些特殊的处理,这时便可以采用代理模式了。

代理模式分为动态代理和静态代理,其中静态代理比较简单,它要求代理类和被代理类必须事先已经存在,代理类的接口和所代理方法都已明确指定。如果需要为不同的真实主题类提供代理类或者代理一个真实主题类中的不同方法,都需要增加新的代理类,这将导致系统中的类个数急剧增加,因此需要想办法减少系统中类的个数。动态代理可以让系统能够根据实际需要来动态创建代理类,让同一个代理类能够代理多个不同的真实主题类而且可以代理不同的方法。

下面先来一个简单的静态代理的例子(这里把所有类放在同一个java文件中,下同):

interface Subject { public void fun(); } class SubjectImpl implements Subject { public void fun() { System.out.println("this is subject impl"); } } class Proxy implements Subject { private Subject subject = null;//将需要被代理的类设置为类属性 public void fun() { before();//do something before.. if(subject == null) { subject = new SubjectImpl();//初始化 subject.fun();//实际调用的是被代理类中的fun方法 } after();//do something after… } private void before() { System.out.println("before......."); } private void after() { System.out.println("after........"); } } class Main { public static void main(String[] args) { Proxy proxy = new Proxy(); proxy.fun(); } }


 

例子比较简单,就不分析了。

下面我们看下动态代理。

从JDK 1.3开始,Java语言提供了对动态代理的支持,Java语言实现动态代理时需要用到位于java.lang.reflect包中的一些类,现简要说明如下:

(1) Proxy类

Proxy类提供了用于创建动态代理类和实例对象的方法,它是所创建的动态代理类的父类,它最常用的方法如下:

·         public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces):该方法用于返回一个Class类型的代理类,在参数中需要提供类加载器并需要指定代理的接口数组(与真实主题类的接口列表一致)。

·         public static Object newProxyInstance(ClassLoader loader, Class<?>[]interfaces, InvocationHandler h):该方法用于返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示代理类所实现的接口列表(与真实主题类的接口列表一致),第三个参数h表示所指派的调用处理程序类。

(2) InvocationHandler接口

InvocationHandler接口是代理处理程序类的实现接口,该接口作为代理实例的调用处理者的公共父类,每一个代理类的实例都可以提供一个相关的具体调用处理者(InvocationHandler接口的子类)。在该接口中声明了如下方法:

·         public Object invoke(Objectproxy, Method method, Object[] args):该方法用于处理对代理类实例的方法调用并返回相应的结果,当一个代理实例中的业务方法被调用时将自动调用该方法。invoke()方法包含三个参数,其中第一个参数proxy表示代理类的实例,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组。

动态代理类需要在运行时指定所代理真实主题类的接口,客户端在调用动态代理对象的方法时,调用请求会将请求自动转发给InvocationHandler对象的invoke()方法,由invoke()方法来实现对请求的统一处理。

具体由如下几种方式:

1.       常规使用:

class InvocationHandlerImpl implements InvocationHandler { private Object target = null; InvocationHandlerImpl(Object target) { this.target = target; } public Object invoke(Object proxy,Method method,Object[] args)throws Throwable { Object obj = null; if(method.getName().equals("fun")) { System.out.println("before..."); obj = method.invoke(target,args); System.out.println("after..."); } else { obj = method.invoke(target,args); } return obj; } } class Main//测试 { public static void main(String[] args) { SubjectImpl subimpl = new SubjectImpl(); InvocationHandlerImpl handler = new InvocationHandlerImpl(subimpl); Subject sub = (Subject)Proxy.newProxyInstance(subimpl.getClass().getClassLoader(), subimpl.getClass().getInterfaces(),handler); sub.fun(); } }


 

2.       通过匿名内部类方式使用:

class Main { public static void main(String[] args) { final SubjectImpl sub = new SubjectImpl(); Subject su = (Subject)Proxy.newProxyInstance(sub.getClass().getClassLoader(), sub.getClass().getInterfaces(),new InvocationHandler() { public Object invoke(Object proxy,Method method,Object[] args)throws Throwable { Object obj = null; if(method.getName().equals("func")) { System.out.println("before..."); obj = method.invoke(sub,args); System.out.println("after..."); } else { obj = method.invoke(sub,args); } return obj; } } ); su.fun(); } }

3.在InvocationHandler实现类内部创建一个bind方法,用来返回target类实例:

class InvocationHandlerImpl implements InvocationHandler { private Object target = null; public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } public Object invoke(Object proxy, Method method,Object[] args) throws Throwable { Object obj = null; if(method.getName().equals("fun")) { before(); obj = method.invoke(target,args); after(); } else { obj = method.invoke(target,args); } return obj; //return null; } private void before() { System.out.println("before..."); } private void after() { System.out.println("after..."); } } class Main { public static void main(String[] args) { InvocationHandlerImpl proxy = new InvocationHandlerImpl(); Subject sub = (Subject)proxy.bind(new SubjectImpl()); sub.fun(); } }



 

 

    你可能想看:

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

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

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

    分享给朋友:

    “【设计模式】代理模式设计模式 代理” 的相关文章

    存储VPS:高效处理大量数据,灵活配置,按需付费

    什么是存储VPS 存储VPS是一种专门为处理大量数据而设计的虚拟专用服务器。它提供了广泛的磁盘空间,并且通常针对高容量存储需求进行了优化。无论是个人用户还是企业用户,存储VPS都能满足他们对数据存储的高要求。这种服务器不仅具备强大的存储能力,还提供了灵活的配置选项,用户可以根据自己的需求选择合适的硬...

    越南VPS服务全解析:如何选择性价比最高的虚拟服务器

    越南VPS市场近年来发展迅速,吸引了越来越多的用户和投资者。越南的地理位置和互联网基础设施的不断完善,使其成为东南亚地区VPS服务的重要节点。无论是本地企业还是国际用户,越南VPS都提供了多样化的选择。 越南VPS的市场现状 越南VPS市场正处于快速扩展阶段。随着越南互联网普及率的提升和数字化转型的...

    Hostloc论坛:主机爱好者的交流与协作平台

    在这个快速发展的互联网时代,信息交流变得尤为重要,Hostloc论坛正是这样一个致力于主机相关话题交流的平台。论坛的创办源于一群热衷于主机技术的人士,他们希望通过建立一个开放的讨论空间,分享自己的经验和见解。随着时间的推移,Hostloc逐渐发展成为一个全球知名的主机论坛,吸引了来自各个国家的用户共...

    香港云服务器:灵活选择与网络优势助力企业发展

    香港云服务器作为一种现代化的网络托管服务,逐渐成为越来越多企业和个人用户的首选。这种服务的核心就是将服务器放置在香港的数据中心,提供灵活的云计算资源。对于希望在云端运作的用户来说,了解香港云服务器的定义与特点是非常重要的。 首先,香港云服务器的产品类型多种多样,从轻量云主机到快杰云主机,再到裸金属服...

    全面解析服务器与主机:性能优化与选择策略

    1.1 服务器与主机的定义与基本概念 在信息技术的世界中,服务器和主机是两个不可或缺的概念。我常常将服务器视为一个强大的计算机,专门用于处理、存储和管理数据。它主要面向网络上的其他设备,承担着提供服务的重任。比如,网站的后台就是一个服务器,负责处理访问请求、存储用户数据等。而主机则是一个更广泛的术语...

    WordPress reCAPTCHA插件:提升网站安全与用户体验的最佳解决方案

    reCAPTCHA插件概述 在今天的网络环境中,安全性愈发重要,尤其是对于使用WordPress的网站。WordPress reCAPTCHA插件成为了一种流行的解决方案,它借助Google强大的reCAPTCHA服务,帮助我们有效地区分真实用户和可能扰乱网站的机器程序。在我接触这个插件之后,发现它...