GoF之代理模式
代理模式的作用当一个对象需要受到保护的时候可以使用代理对象去完成某个行为。需要给某个对象进行功能增强的时候可以找一个代理进行增强。A对象和B对象无法直接交互时也可以使用代理模式来完成。代理模式中的三个角色目标对象代理对象目标对象和代理对象的公共接口如果使用代理模式的话客户端程序是无法察觉的客户端在使用代理对象的时候就像在使用目标对象。代理模式分为静态代理和动态代理。静态代理目标对象类// 目标对象 public class OrderServiceImpl implements OrderService{ Override public void generateOrder() { System.out.println(生成订单); } Override public void modifyOrder() { System.out.println(修改订单); } Override public void detailOrder() { System.out.println(查看订单详情); } }代理对象类// 代理对象 public class OrderServiceProxy implements OrderService{ // 代理对象中含有目标对象的引用 // 这里使用OrderService类型因为他耦合度低 private OrderService orderService; // 构造方法传入目标对象 public OrderServiceProxy(OrderService orderService) { this.orderService orderService; } Override public void generateOrder() { // 功能增强统计方法执行时间 long begin System.currentTimeMillis(); orderService.generateOrder(); long end System.currentTimeMillis(); System.out.println(生成订单耗时 (end - begin) ms); } Override public void modifyOrder() { long begin System.currentTimeMillis(); orderService.modifyOrder(); long end System.currentTimeMillis(); System.out.println(修改订单耗时 (end - begin) ms); } Override public void detailOrder() { long begin System.currentTimeMillis(); orderService.detailOrder(); long end System.currentTimeMillis(); System.out.println(查看订单详情耗时 (end - begin) ms); } }公共接口// 订单服务接口 // 目标对象和代理对象的公共接口 public interface OrderService { // 生成订单 void generateOrder(); // 修改订单 void modifyOrder(); // 查看订单详情 void detailOrder(); }测试// 实现目标对象方法执行时间的统计 public static void main(String[] args) { // 创建目标对象 OrderService orderService new OrderServiceImpl(); // 创建代理对象同时将目标对象传入代理对象中 OrderServiceProxy orderServiceProxy new OrderServiceProxy(orderService); // 通过代理对象调用目标对象的方法 orderServiceProxy.generateOrder(); orderServiceProxy.modifyOrder(); orderServiceProxy.detailOrder(); }静态代理优点1.解决了ocp问题 2.采用代理模式的has a。降低了耦合度。静态代理的缺点假设系统中有上千个接口每个接口都需要写代理类这样类的数量会急剧膨胀不好维护。那怎么解决类爆炸的问题呢采用动态代理。 动态代理还是代理模式只不过是在内存中为我们动态的生成一个class字节码这个字节码就是代理类。动态代理在程序运行阶段在内存中动态生成代理类成为动态代理。目的是减少代理类的数量。常见的动态代理技术有JDK动态代理只能代理接口、CGLIB动态代理、Javassist动态代理。JDK动态代理公共接口 和目标对象类引用 上面的代码。Jdk动态代理不需要写代理类jdk会在内存中自动生成代理类因此直接在客户端代码里直接调用客户端代码public class Client { public void main() { // 1. 创建目标对象 OrderService orderService new OrderServiceImpl(); // 2. 创建InvocationHandler对象 // 3. 创建代理对象 // 1. Proxy.newProxyInstance 的作用是创建代理对象。其实做了两件事: // 1). 在内存中动态的构建一个类, // 2). 这个类要实现接口, 这个接口就是目标对象的接口,并且new了一个对象 // 2. 这个方法的三个参数: // 1). ClassLoader: 类加载器, 用于加载内存中的代理对象类. 和目标对象使用相同的类加载器 // 2). Class[]: 字节码数组, 代理对象和目标对象实现相同的接口. 用于让代理对象和目标对象具有相同的方法 // 3). InvocationHandler: 调用处理器对象,他是一个接口 这个调用处理器用于编写增强代码 OrderService o (OrderService)Proxy.newProxyInstance(OrderService.class.getClassLoader(), orderService.getClass().getInterfaces(), new TimerInvocationHandler(orderService)); // 4. 通过代理对象调用方法 // 调用代理对象的代理方法时如果代理方法的作用是功能增强那目标对象的目标方法必须执行。 o.generateOrder(); } }调用处理器类/** * 负责计时的一个调用处理器类 * 在这个调用处理器中编写增强代码 * 这个调用处理器只需要一个就好 */ public class TimerInvocationHandler implements InvocationHandler { // 目标对象,就是要被增强的对象 private Object target; // 构造方法传入目标对象 public TimerInvocationHandler(Object target) { this.target target; } // 这个方法必须是invoke()方法,因为jdk在底层会调用这个方法 // 这个方法什么时候调用? // 什么时候通过代理对象调用方法的时候就会调用这个invoke()方法 // 这个方法的参数: // proxy: 代理对象,就是通过Proxy.newProxyInstance()方法创建的代理对象 // method: 目标对象的目标方法,这就是要执行的目标方法 // args: 目标方法上的参数 Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 功能增强 Long begin System.currentTimeMillis(); Object invoke method.invoke(target, args); Long end System.currentTimeMillis(); System.out.println(方法执行耗时 (end - begin) ms); return invoke; } }CGLIB动态代理既可以代理接口也可以代理类。底层采用继承的方式实现因此被代理的目标类不能被final修饰。目标类// 目标类 public class UserService { public boolean login(String username, String password) { System.out.println(用户登录用户名 username 密码 password); return admin.equals(username) 123456.equals(password); } public void logout(String username) { System.out.println(用户退出登录用户名 username); } }客户端代码public static void main(String[] args) { // 创建字节码增强对象 // 这个对象是cglib的核心对象依靠它来生成代理类 Enhancer enhancer new Enhancer(); // 设置父类也就是目标类 enhancer.setSuperclass(UserService.class); // 设置回调函数等同于jdk动态代理的中的调用处理器 // 在cglib中是实现方法拦截器MethodInterceptor接口 enhancer.setCallback(new TimerMethodInterceptor()); UserService userServiceProxy (UserService)enhancer.create(); boolean login userServiceProxy.login(admin, 123456); System.out.println(login?登录成功:登录失败); userServiceProxy.logout(admin); }增强代码写在方法拦截器里面public class TimerMethodInterceptor implements MethodInterceptor { Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { Long startTime System.currentTimeMillis(); Object o1 methodProxy.invokeSuper(o, objects); Long endTime System.currentTimeMillis(); System.out.println(方法 method.getName() 执行耗时 (endTime - startTime) ms); return o1; } }注意:在jdk17环境下cglib动态代理功能启动时会报错需要添加启动时参数设置:vm 参数--add-opens java.base/java.langALL-UNNAMEDprogram 参数:--add-opens java.base/sun.net.utilALL-UNNAMED面向切面编程AOP在一个系统中一般会有许多系统服务如日志事务管理、安全等。这些服务成为交叉业务。这些交叉业务是通用的。如果在每一个业务处理过程中都掺杂这些交叉业务代码会出现2个问题交叉业务代码在多个业务中反复出现。代码没有得到复用修改这些代码会非常困难。开发人员无法专业核心业务代码在编写核心业务代码时还要处理这些交叉业务代码。这就需要使用AOP来解决以上问题。总之AOP就是将与核心业务无关的代码独立的抽取出来。形成一个独立的组件然后以横向交叉的方式应用到业务流程当中的过程。aop底层使用动态代理技术实现。spring AOP 使用的时jdk动态代理cglib动态代理。spring 在这2种动态代理种灵活切换。如果是代理接口则使用jdk动态代理如果代理某个类则使用cglib。当然也可以手动配置来强制使用cglib。AOP的七大术语连接点Joinpoint在程序执行流程中可以织入切面的位置。方法的执行前后异常抛出之后等位置。连接点描述的是位置。切点Pointcut在程序执行流程中真正织入切面的方法。一个切点对应多个连接点切点描述的是方法。通知Advice通知又叫增强就是具体你要织入的的代码。通知包括前置通知、后置通知、环绕通知、异常通知、最终通知。通知描述的是代码。切面Aspect切点通知就是切面。织入Weaving把通知应用到目标对象上的过程。代理对象Proxy一个目标对象被织入通知后产生的新对象。目标对象Target被织入通知的对象。public void main(String[] args) { try { // Joint point 连接点 do1(); // Pointcut 切点 // Joint point 连接点 do2();// Pointcut 切点 // Joint point 连接点 do3();// Pointcut 切点 // Joint point 连接点 do4();// Pointcut 切点 // Joint point 连接点 do5();// Pointcut 切点 // Joint point 连接点 } catch (Exception e) { // Joint point 连接点 } }切点表达式

相关新闻

2026轮廓仪安装环境要求与隔振方案全解析

2026轮廓仪安装环境要求与隔振方案全解析

在三维光学轮廓仪的日常使用中,环境振动是影响测量数据准确性的最主要外部因素之一。无论是白光干涉还是共聚焦测量原理,绝大多数光学轮廓仪对亚微米至纳米级的外部振动都高度敏感。用户在发现表面形貌测量数据出现跳变、重复性差、干涉条纹不稳定或3D重…

2026/7/1 7:53:17阅读更多 →
VMware虚拟机磁盘直通主机的3种实战路径:从vmdk挂载到RDM配置,一文吃透全链路

VMware虚拟机磁盘直通主机的3种实战路径:从vmdk挂载到RDM配置,一文吃透全链路

更多请点击: https://intelliparadigm.com 第一章:VMware虚拟机磁盘直通主机的技术全景与核心价值 VMware虚拟机磁盘直通(Raw Device Mapping, RDM)是一种将物理存储设备(如SAN LUN或本地NVMe SSD)直接映射…

2026/7/1 7:53:17阅读更多 →
VMware磁盘扩容避坑手册(2024最新版):绕过3大致命陷阱——空间不释放、分区识别失败、Guest OS拒绝挂载

VMware磁盘扩容避坑手册(2024最新版):绕过3大致命陷阱——空间不释放、分区识别失败、Guest OS拒绝挂载

更多请点击: https://kaifayun.com 第一章:VMware磁盘扩容避坑手册(2024最新版)导言 VMware虚拟机磁盘扩容看似简单,实则暗藏多重陷阱:从底层存储格式兼容性、分区表类型限制,到操作系统内核识…

2026/7/1 7:53:17阅读更多 →
3个步骤让Windows电脑变身安卓应用中心:APK安装器使用指南

3个步骤让Windows电脑变身安卓应用中心:APK安装器使用指南

3个步骤让Windows电脑变身安卓应用中心:APK安装器使用指南 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾经因为手机屏幕太小而烦恼?或…

2026/7/1 9:18:29阅读更多 →
Postman接口压力测试六步法:快速验证并发性能的轻量级方案

Postman接口压力测试六步法:快速验证并发性能的轻量级方案

1. 项目概述:为什么Postman也能做压力测试?很多开发者和测试同学一提到接口压力测试,脑海里蹦出来的第一个工具可能就是JMeter或者LoadRunner。这很正常,这些工具功能强大,是专业的性能测试利器。但有时候,…

2026/7/1 9:18:29阅读更多 →
Rich:让 Python 终端输出变得丰富好看

Rich:让 Python 终端输出变得丰富好看

文章目录Rich:让 Python 终端输出变得丰富好看Rich:让 Python 终端输出变得丰富好看 Rich 是一个 Python 库,用于在终端中生成富文本和美观的格式化输出。它在 GitHub 上收获了 56,692 个 Star。 这个库可以让终端输出变得丰富多彩。通过 Ri…

2026/7/1 9:18:29阅读更多 →
深入解析Widevine L3 DRM:从原理到逆向工程实践

深入解析Widevine L3 DRM:从原理到逆向工程实践

1. 项目概述:为什么我们要深入理解Widevine L3解密?如果你经常在流媒体平台追剧看电影,尤其是那些需要付费订阅的平台,那么你其实每天都在和DRM(数字版权管理)技术打交道。Widevine就是这套技术体系中最核心…

2026/7/1 9:18:29阅读更多 →
月入五万的蓝海赛道,两年做到成都头部

月入五万的蓝海赛道,两年做到成都头部

最近好几个同学来问节气礼盒项目,说翻了一圈,发现我们宣传得不多,问我能不能再讲透一点。行,今天咱们敞开聊聊。 先说一个大多数人认为的误区:提到端午粽子、中秋月饼,第一反应是不是街边糕点店、网红零食&…

2026/7/1 9:18:29阅读更多 →
告别杜邦线!用STM32F103C6T6自制MPU6050+QMC5883L九轴传感器模块(含蓝牙无线传输)

告别杜邦线!用STM32F103C6T6自制MPU6050+QMC5883L九轴传感器模块(含蓝牙无线传输)

从零打造九轴传感器模块:STM32F103C6T6与MPU6050/QMC5883L的硬件集成与无线传输实战看着桌面上散落的开发板、传感器模块和纠缠不清的杜邦线,每个嵌入式开发者都经历过这种"蜘蛛网"式的开发阶段。但当我们准备将原型转化为实际产品时&#xff…

2026/7/1 9:13:24阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/1 4:42:14阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/1 5:19:01阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/1 0:01:44阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/1 0:01:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/1 0:01:44阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/1 0:01:44阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/1 0:01:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/1 0:01:44阅读更多 →