当前位置: 首页 > news >正文

深入理解代理模式(Proxy Pattern)及其实际应用

引言

在软件开发中,有时候我们需要在不改变现有代码的情况下添加一些功能,比如延迟初始化、访问控制、日志记录等。代理模式(Proxy Pattern)通过代理对象控制对原对象的访问,为现有代码添加了额外的功能。本篇文章将详细介绍代理模式的概念、应用场景、优缺点,并通过Java代码示例展示代理模式的实际应用。

1. 什么是代理模式?

代理模式是一种结构型设计模式,它提供一个代理对象控制对原对象的访问。代理模式可以在不修改原对象的情况下,向其添加一些功能,比如访问控制、延迟加载、日志记录等。

代理模式的结构

代理模式包含以下几个主要角色:

  • 抽象主题(Subject):定义代理类和真实主题类的公共接口。
  • 真实主题(RealSubject):实现抽象主题接口,定义真实对象。
  • 代理(Proxy):实现抽象主题接口,包含对真实主题对象的引用,并可以在调用真实主题对象前后添加额外功能。

2. 代理模式的代码示例

示例背景

假设我们有一个简单的业务服务类,它有一个方法需要在调用前后执行一些日志记录。我们可以使用代理模式来实现这一点。

抽象主题接口

首先,我们定义抽象主题接口:

// 抽象主题接口
interface BusinessService {void performTask();
}

真实主题类

然后,我们定义真实主题类:

// 真实主题类
class RealBusinessService implements BusinessService {@Overridepublic void performTask() {System.out.println("Performing the main task...");}
}

代理类

接下来,我们定义代理类,在方法调用前后执行增强内容:

// 代理类
class BusinessServiceProxy implements BusinessService {private RealBusinessService realBusinessService;public BusinessServiceProxy(RealBusinessService realBusinessService) {this.realBusinessService = realBusinessService;}@Overridepublic void performTask() {logBefore();realBusinessService.performTask();logAfter();}private void logBefore() {System.out.println("Log before method execution");}private void logAfter() {System.out.println("Log after method execution");}
}

客户端代码

最后,我们在客户端代码中使用代理模式:

public class ProxyPatternDemo {public static void main(String[] args) {RealBusinessService realBusinessService = new RealBusinessService();BusinessService businessService = new BusinessServiceProxy(realBusinessService);// 调用方法前后会执行增强内容businessService.performTask();}
}

输出

Log before method execution
Performing the main task...
Log after method execution

解释

在这个示例中,我们定义了一个业务服务接口 BusinessService 及其实现类 RealBusinessService,并通过代理类 BusinessServiceProxy 在方法调用前后添加了日志记录功能。代理类在调用真实业务服务对象的方法前后,分别调用了 logBeforelogAfter 方法,从而实现了在方法调用前后执行增强内容。

3. 代理模式在实际框架中的应用

代理模式在许多实际框架中都有广泛的应用。下面我们以Spring AOP(面向切面编程)为例,展示代理模式如何在实际应用中为现有代码添加额外功能。

案例分析:Spring AOP

Spring AOP通过代理对象为现有代码添加了日志记录、事务管理、权限控制等功能。Spring AOP可以在不修改现有代码的情况下,通过代理对象在方法调用前后添加额外的功能。

具体实现

下面是一个使用Spring AOP的示例:

1. 添加依赖

首先,在Maven的pom.xml文件中添加Spring AOP的依赖:

<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.9</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version>
</dependency>
2. 目标对象

定义业务服务类:

// 目标对象
public class MyService {public void performTask() {System.out.println("Performing task...");}
}
3. 切面类

定义切面类,在方法调用前后执行增强内容:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;@Aspect
public class LoggingAspect {@Before("execution(* MyService.performTask(..))")public void logBefore() {System.out.println("Log before method execution");}@After("execution(* MyService.performTask(..))")public void logAfter() {System.out.println("Log after method execution");}
}
4. Spring 配置文件

定义Spring配置文件(aop-config.xml):

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="myService" class="MyService"/><bean id="loggingAspect" class="LoggingAspect"/><aop:config><aop:aspect ref="loggingAspect"><aop:pointcut id="performTaskPointcut" expression="execution(* MyService.performTask(..))"/><aop:before method="logBefore" pointcut-ref="performTaskPointcut"/><aop:after method="logAfter" pointcut-ref="performTaskPointcut"/></aop:aspect></aop:config>
</beans>
5. 客户端代码

在客户端代码中使用Spring AOP:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class SpringAOPDemo {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("aop-config.xml");MyService myService = (MyService) context.getBean("myService");myService.performTask();}
}

输出

Log before method execution
Performing task...
Log after method execution

解释

在这个示例中,Spring AOP通过代理对象在方法调用前后添加了日志记录功能,实现了代理模式。在Spring AOP配置文件中,我们定义了切面(Aspect)和切入点(Pointcut),并指定在目标方法调用前后执行增强内容。

4. 代理模式的优缺点

优点

  • 控制对象访问:可以在访问对象时添加额外的功能,比如权限控制、延迟加载等。
  • 增强对象功能:可以在不修改现有代码的情况下,为对象添加新的功能。
  • 灵活性高:代理对象可以灵活地控制对真实对象的访问。

缺点

  • 增加复杂性:需要引入代理对象,增加了系统的复杂性。
  • 性能开销:代理对象会增加方法调用的开销,影响系统性能。

5. 总结

代理模式通过代理对象控制对原对象的访问,为现有代码添加了额外的功能。在业务服务的示例中,我们展示了如何通过代理类在方法调用前后执行增强内容,实现了日志记录功能。在Spring AOP中的应用展示了代理模式的实际效果,极大地增强了系统的功能和灵活性。

希望这篇文章对你理解代理模式有所帮助。如果觉得本文内容有价值,请点赞、收藏和关注我们,获取更多设计模式的精彩内容!

相关文章:

深入理解代理模式(Proxy Pattern)及其实际应用

引言 在软件开发中&#xff0c;有时候我们需要在不改变现有代码的情况下添加一些功能&#xff0c;比如延迟初始化、访问控制、日志记录等。代理模式&#xff08;Proxy Pattern&#xff09;通过代理对象控制对原对象的访问&#xff0c;为现有代码添加了额外的功能。本篇文章将详…...

Elasticsearch (1):ES基本概念和原理简单介绍

Elasticsearch&#xff08;简称 ES&#xff09;是一款基于 Apache Lucene 的分布式搜索和分析引擎。随着业务的发展&#xff0c;系统中的数据量不断增长&#xff0c;传统的关系型数据库在处理大量模糊查询时效率低下。因此&#xff0c;ES 作为一种高效、灵活和可扩展的全文检索…...

【Python爬虫】Python爬取喜马拉雅,爬虫教程!

一、思路设计 &#xff08;1&#xff09;分析网页 在喜马拉雅主页找到自己想要的音频&#xff0c;得到目标URL&#xff1a;https://www.ximalaya.com/qinggan/321787/ 通过分析页面的网络抓包&#xff0c;最终的到一个比较有用的json数据包 通过分析&#xff0c;得到了发送json…...

基于Jmeter的分布式压测环境搭建及简单压测实践

写在前面 平时在使用Jmeter做压力测试的过程中&#xff0c;由于单机的并发能力有限&#xff0c;所以常常无法满足压力测试的需求。因此&#xff0c;Jmeter还提供了分布式的解决方案。本文是一次利用Jmeter分布式对业务系统登录接口做的压力测试的实践记录。按照惯例&#xff0…...

IDEA常用代码模板

在 IntelliJ IDEA 中,常用代码模板可以帮助你快速生成常用的代码结构和模式。以下是一些常用的代码模板及其使用方法: 动态模板(Live Templates) psvm:生成 public static void main(String[] args) 方法。sout:生成 System.out.println(); 语句。soutv:生成 System.ou…...

基于大语言模型的多意图增强搜索

随着人工智能技术的蓬勃发展&#xff0c;大语言模型&#xff08;LLM&#xff09;如Claude等在多个领域展现出了卓越的能力。如何利用这些模型的语义分析能力&#xff0c;优化传统业务系统中的搜索性能是个很好的研究方向。 在传统业务系统中&#xff0c;数据匹配和检索常常面临…...

【ai】ubuntu18.04 找不到 nvcc --version问题

nvcc --version显示command not found问题 这个是cuda 库: windows安装了12.5 : 参考大神:解决nvcc --version显示command not found问题 原文链接:https://blog.csdn.net/Flying_sfeng/article/details/103343813 /usr/local/cuda/lib64 与 /usr/local/cuda-11.3/lib64 完…...

深入了解DDoS攻击及其防护措施

深入了解DDoS攻击及其防护措施 分布式拒绝服务&#xff08;Distributed Denial of Service&#xff0c;DDoS&#xff09;攻击是当今互联网环境中最具破坏性和普遍性的网络威胁之一。DDoS攻击不仅危及企业的运营&#xff0c;还可能损害其声誉&#xff0c;造成客户信任度的下降。…...

【面试系列】产品经理高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…...

前端特殊字符数据,后端接收产生错乱,前后端都需要处理

前端&#xff1a; const data {createTime: "2024-06-11 09:58:59",id: "1800346960914579456",merchantId: "1793930010750218240",mode: "DEPOSIT",channelCode: "if(amount > 50){iugu2pay;} else if(amount < 10){iu…...

力扣热100 哈希

哈希 1. 两数之和49.字母异位词分组128.最长连续序列 1. 两数之和 题目&#xff1a;给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。你可以假设每种输入只会对应一个答案。…...

[图解]SysML和EA建模住宅安全系统-05-参数图

1 00:00:01,140 --> 00:00:03,060 这是实数没错&#xff0c;这是分钟 2 00:00:03,750 --> 00:00:07,490 但是你在这里选&#xff0c;选不了的 3 00:00:07,500 --> 00:00:09,930 因为它这里不能够有那个 4 00:00:11,990 --> 00:00:13,850 但是我们前面这里 5 00…...

JavaScript——对象的创建

目录 任务描述 相关知识 对象的定义 对象字面量 通过关键字new创建对象 通过工厂方法创建对象 使用构造函数创建对象 使用原型(prototype)创建对象 编程要求 任务描述 本关任务&#xff1a;创建你的第一个 JavaScript 对象。 相关知识 JavaScript 是一种基于对象&a…...

大二暑假 + 大三上

希望&#xff0c;暑假能早睡早起&#xff0c;胸围达到 95&#xff0c;腰围保持 72&#xff0c;大臂 36&#xff0c;小臂 32&#xff0c;小腿 38&#x1f36d;&#x1f36d; 目录 &#x1f348;暑假计划 &#x1f339;每周进度 &#x1f923;寒假每日进度&#x1f602; &…...

C语言使用先序遍历创建二叉树

#include<stdio.h> #include<stdlib.h>typedef struct node {int data;struct node * left;struct node * right; } Node;Node * createNode(int val); Node * createTree(); void freeTree(Node * node);void preOrder(Node * node);// 先序创建二叉树 int main()…...

如何在服务器中安装anaconda

文章目录 Step1: 下载 Anaconda方法1&#xff1a;下载好sh文件上传到服务器安装方法2&#xff1a;在线下载 Step2: 安装AnacondaStep3: 配置环境变量Step 4: 激活AnacondaStep4: 检验安装是否成功 Step1: 下载 Anaconda 方法1&#xff1a;下载好sh文件上传到服务器安装 在浏览…...

夸克网盘拉新暑期大涨价!官方授权渠道流程揭秘

夸克网盘拉新暑期活动来袭&#xff0c;价格大涨&#xff01;从7月1日开始持续两个月&#xff0c;在这两个月里夸克网盘拉新的移动端用户&#xff0c;一个从原来的5元涨到了10元。这对做夸克网盘拉新的朋友来说&#xff0c;真的是福利的。趁着暑期时间多&#xff0c;如果有想做夸…...

机器学习(三)

机器学习 4.回归和聚类算法4.1 线性回归4.1.1 线性回归的原理4.1.2 线性回归的损失和优化原理 4.2 欠拟合与过拟合4.2.1 定义4.2.2 原因以及解决方法4.2.3 正则化 4.3 线性回归改进-岭回归4.3.1 带L2正则化的线性回归-岭回归4.3.2 API 4.4 分类算法-逻辑回归与二分类4.4.1 定义…...

PostgreSQL 基本SQL语法(二)

1. SELECT 语句 1.1 基本 SELECT 语法 SELECT 语句用于从数据库中检索数据。基本语法如下&#xff1a; SELECT column1, column2, ... FROM table_name; 例如&#xff0c;从 users 表中检索所有列的数据&#xff1a; SELECT * FROM users; 1.2 使用 WHERE 条件 WHERE 子…...

linux 控制台非常好用的 PS1 设置

直接上代码 IP$(/sbin/ifconfig eth0 | awk /inet / {print $2}) export PS1"\[\e[35m\]^o^\[\e[0m\]$ \[\e[31m\]\t\[\e[0m\] [\[\e[36m\]\w\[\e[0m\]] \[\e[32m\]\u\[\e[0m\]\[\e[33m\]\[\e[0m\]\[\e[34m\]\h(\[\e[31m\]$IP\[\e[m\])\[\e[0m\]\n\[\e[35m\].O.\[\e[0m\]…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...