代理模式---静态代理和动态代理

news/2024/10/9 5:48:38/

代理模式

        代理模式给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式

        代理模式角色分为 3 种:

Subject(抽象主题角色):定义代理类和真实主题的公共对外方法,通常被设计成接口;

RealSubject(真实主题角色):真正实现业务逻辑的类;

Proxy(代理主题角色):用来代理和封装真实主题;

        代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。

         如果根据字节码的创建时机来分类,可以分为静态代理动态代理

静态代理

        所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题角色的关系在运行前就确定了

        假设有UserService接口及其实现类UserServiceImpl,我们需要在不改变实现类代码的基础上,增加日志记录的功能。

//Subject

java">public interface UserService {public void select();public void update();}

//RealSubject 真实主题对象(真正的业务类)

java">public class UserServiceImpl implements UserService{	public void select() {System.out.println("查询selectById");		}	public void update() {System.out.println("更新updateById");}
}

//Proxy 代理对象

java">public class UserServiceProxy implements UserService{//创建真正的主题对象private UserServiceImpl realUserService=new UserServiceImpl ();@Overridepublic void select() {long begin=System.currentTimeMillis();realUserService.select();long end=System.currentTimeMillis();System.out.println("select的执行时间为:"+(end-begin)+"毫秒");}@Overridepublic void update() {// TODO Auto-generated method stublong begin=System.currentTimeMillis();realUserService.update();long end=System.currentTimeMillis();System.out.println("update的执行时间为:"+(end-begin)+"毫秒");}
}

//Test测试类

java">public class Test {public static void main(String[] args) {//创建代理对象UserServiceProxy proxy=new UserServiceProxy();proxy.select();proxy.update();}
}

//运行结果:

查询selectById
select的执行时间为:0毫秒
更新updateById
update的执行时间为:0毫秒

        通过静态代理,我们可以达成增强功能而不污染原代码,这是静态代理的优点。但是在一些场景复杂的时候,静态代理的缺点也会暴露出来:

1、 当需要代理多个类的时候,由于代理对象要实现与目标对象一致的接口,有两种方式

只维护一个代理类,由这个代理类实现多个接口,但是这样就导致代理类过于庞大,导致代码可读性差。

新建多个代理类,每个目标对象对应一个代理类,但是这样会产生过多的代理类,难以管理。

2、 当接口需要增加、删除、修改方法的时候,目标对象与代理类都要同时修改,不易维护

动态代理

        Java中两种常见的动态代理方式:JDK原生动态代理CGLIB动态代理(第三方开源类库)。

JDK动态代理

        JDK动态代理主要涉及两个类:java.lang.reflect.Proxy 和java.lang.reflect.InvocationHandler。我们通过编写一个调用逻辑处理器 LogHandler 类案例来提供日志增强功能,并实现 InvocationHandler 接口;在 LogHandler 中维护一个目标对象,这个对象是被代理的对象(真实主题角色);在 invoke()方法中编写方法调用的逻辑处理。

//准备好两个真实主题对象及其接口:

//1.UserService和UserServiceImp

java">public interface UserService {public void select();public void update();}
java">//RealSubject 真实主题对象(真正的业务类)
public class UserServiceImpl implements UserService{	public void select() {System.out.println("查询selectById");		}	public void update() {System.out.println("更新updateById");}
}

//2.OrderService 和OrderServiceImp

java">public interface OrderService {public void creat(int money,int uid);}
java">public class OrderServiceImpl implements OrderService{@Overridepublic void creat(int money, int uid) {System.out.printf("商品%d的价格是:%d",uid,money);System.out.println();}}

//InvocationHandler 接口的实现类

java">//用于检测方法运行时间的Handler执行器
public class PerformanceInvocationHandler implements InvocationHandler{private Object real;public PerformanceInvocationHandler(Object real) {this.real=real;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//开始时间long begin=System.currentTimeMillis();//真实业务对象当前的执行方法(基于反射)//相当于调用了creat()、select()或update()方法//传入的真实主题对象是谁,就调用谁的方法Object returnValue=method.invoke(real, args);//结束时间long end=System.currentTimeMillis();System.out.println("方法耗时:"+(end-begin)+"毫秒");return returnValue;}}

//实现OrderService代理的测试类

java">public class Test01 {public static void main(String[] args) {//真实主题对象OrderServiceImpl realOrderService=new OrderServiceImpl();//获取类加载器ClassLoader classLoader=realOrderService.getClass().getClassLoader();//接口列表Class[] interfaces=realOrderService.getClass().getInterfaces();//创建InvocationHandler对象(动态代理执行逻辑)PerformanceInvocationHandler h=new PerformanceInvocationHandler(realOrderService);//创建一个代理对象OrderService orderServiceProxy=(OrderService)Proxy.newProxyInstance(classLoader, interfaces, h);/调用方法orderServiceProxy.creat(1234, 1);}}

//运行结果:

商品1的价格是:1234
方法耗时:33毫秒

//实现UserService代理的测试类

java">public class Test02 {public static void main(String[] args) {//创建真实主题对象UserServiceImpl realUserService=new UserServiceImpl();//获取类加载器ClassLoader loader=realUserService.getClass().getClassLoader();//获取接口列表Class[] interfaces=realUserService.getClass().getInterfaces();//HandlerPerformanceInvocationHandler h=new PerformanceInvocationHandler(realUserService);//创建动态代理对象UserService userServiceProxy=(UserService)Proxy.newProxyInstance(loader, interfaces, h);//调用方法userServiceProxy.update();}}

 //运行结果:

更新updateById
方法耗时:0毫秒

        通过动态代理,我们不再需要创建不同代理类来实现不同的逻辑方法。动态代理是通过Proxy创建代理对象,然后将接口方法“代理”给InvocationHandler完成的。


http://www.ppmy.cn/news/1527409.html

相关文章

NLP中文本生成任务

文本生成任务 1.生成式任务2.自回归模型实现3.Encoder-Decoder结构3.1Attention机制出现3.2Attention思想3.3soft - Attention3.4hard - Attention3.5Teacher Forcing3.6详解Mask Attention3.6.1通过Mask控制训练方式 4.生成式任务评价指标5.生成式任务常见问题5.1采样策略5.2指…

批量操作Excel的四个方法(求和、移动、对比、合并)

Excel文件肯定少不了保存大量数据,那么在使用excel的时候会不会要大批量数据进行操作?今天分享4个快速使用excel操作的小技巧。希望能够帮大家提高excel制作效率。 技巧一:快速求和 当你想要分别得到行列的总和,我们可以选中表格…

等保测评后:企业如何持续优化信息安全

通过信息安全等级保护(等保)测评,标志着企业达到了国家规定的安全标准,但这并非终点。在等保测评后,企业需要持续优化信息安全,保持和提升信息安全的防护水平,确保业务的稳定运行和数据的安全。…

开源 AI 智能名片 S2B2C 商城小程序中的全渠道供应策略

摘要:本文深入探讨在开源 AI 智能名片 S2B2C 商城小程序的情境下,全渠道供应的运行机制。阐述各环节企业相互配合的重要性,重点分析零售企业在其中的关键作用,包括协调工作、信息传递、需求把握等方面,旨在实现高效的全…

Android Auto助力电动汽车智能驾驶

随着技术的飞速发展,电动汽车(EVs)成为未来出行的重要趋势。然而,EVs 的普及不仅仅代表环保选择,它们还推动了智能汽车技术的发展。Android Auto 的集成无疑为电动汽车用户带来了更便捷和智能的驾驶体验。 一、智能互联…

computed计算属性与watch侦听器

1.computed计算属性的写法有两种,一种是只读的,只负责展示,另一种可以进行修改,利用get来获取值,利用set来进行修改 2.watch侦听器的写法也有两种,可以直接写成函数,也可以写成对象,…

在 Docker 中部署无头 Chrome:在 Browserless 中运行

什么是 Browserless? Browserless 是一款基于云的浏览器解决方案,旨在实现高效的浏览器自动化、网页抓取和测试。 它利用 Nstbrowser 的指纹库,实现随机指纹切换,确保流畅的数据收集和自动化。得益于其强大的云基础设施&#xf…

iOS18相册大改遭吐槽,iOS18相册恢复iOS17的办法有哪些?

9月17日消息,苹果公司日前已推送了iOS 18正式版更新,除了支持高度自定义主屏幕、应用锁、游戏模式等功能外,自带的相册App也迎来了前所未有的重大更新。 然而,iOS 18正式版推送后,“iOS 18还我妈生相册、iOS 18丑等话…