当前位置: 首页 > 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\]…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...