Java设计模式:代理模式的静态和动态之分(八)

在软件设计中,代理模式是一种常用的设计模式,它为我们提供了一种方式来控制对原始对象的访问。在Java中,代理模式尤其重要,因为它不仅增加了代码的灵活性,还提高了系统的可扩展性。本文将深入探讨Java中的代理模式,包括其定义、分类、实现方式以及实际应用场景。
[参见]:
Java设计模式:核心概述(一)
Java设计模式:单例模式之六种实现方式详解(二)
Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)
Java设计模式:建造者模式之经典与流式的三种实现(四)
Java设计模式:适配器模式的三种形式(五)
Java设计模式:深入装饰器模式的三种写法(六)
Java设计模式:组合模式之透明与安全的两种实现(七)
目录
- 一、代理模式的概念
- 二、代理模式的分类
- 三、代理模式的组成
- 四、代理模式的优缺点
- 4.1 优点
- 4.2 缺点
- 五、代理模式的使用场景
- 1. 日志的采集
- 2. 权限控制
- 3. 实现AOP(面向切面编程)
- 4. MyBatis Mapper
- 5. Spring的事务管理
- 6. 全局捕获异常
- 7. RPC远程调用接口
- 8. 分布式事务原理代理数据源
- 六、代理模式的三种实现
- 6.1 静态代理模式
- 6.2 JDK动态代理的实现
- 6.3 Cglib代理
- 6.4 三种实现的区别和优缺点
- 6.4.1 JDK动态代理
- 6.4.2 cglib动态代理
- 七、注意事项
- 总结
一、代理模式的概念
代理模式(Proxy Pattern)是一种结构型设计模式,它提供了一种将类的功能委托给另一个类的方法。代理类作为原始类的代表,可以在调用原始类的方法之前或之后添加一些额外的逻辑。通过这种方式,代理模式可以控制对原始对象的访问,隐藏其复杂性或增加额外的功能。
二、代理模式的分类
在Java中,代理模式主要分为静态代理和动态代理两种。
- 静态代理:静态代理是在编译时就确定了代理类和被代理类的关系。代理类和被代理类通常会实现相同的接口或继承自相同的父类。静态代理的实现相对简单,但缺点是当需要代理的类增多时,会导致代理类数量剧增,增加了系统的复杂性。
- 动态代理:动态代理是在运行时创建代理类和对象。Java提供了
java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来支持动态代理。动态代理可以灵活地创建代理对象,而无需为每个被代理类编写具体的代理类。这种灵活性使得动态代理在处理大量代理需求时更加高效。
三、代理模式的组成

-
抽象角色(Subject):这是一个接口或抽象类,定义了代理和真实对象需要实现的方法。它充当了客户端与代理/真实对象之间的契约。
-
代理角色(Proxy):代理类实现了抽象角色,并在需要时调用真实对象的方法。代理可以在调用真实对象之前或之后执行一些附加操作,如日志记录、访问控制、性能优化等。
-
真实角色(RealSubject):这是代理所代表的实际对象。它实现了抽象角色,并定义了实际的业务逻辑。客户端通常不直接与真实对象交互,而是通过代理来访问它。
四、代理模式的优缺点
4.1 优点
- 增加额外的操作:代理可以在不修改真实对象的情况下增加额外的操作,如日志记录、安全性检查等。这提供了更好的灵活性和可扩展性。
- 控制访问:代理可以控制对真实对象的访问,例如通过懒加载来延迟创建对象,或者在需要时限制对敏感数据的访问。
- 保护真实对象:代理可以保护真实对象免受不必要的或恶意的访问,从而提高系统的安全性和稳定性。
- 增强功能:代理可以通过装饰器模式的方式增强真实对象的功能,提供额外的服务或修改现有行为。
4.2 缺点
- 性能开销:由于代理增加了额外的层级和调用,可能会导致性能下降。特别是当代理执行复杂操作或网络通信时,这种开销可能更加明显。
- 代码复杂性:实现代理模式可能需要编写额外的代码和类,这可能会增加系统的复杂性和维护成本。需要仔细设计和测试代理类以确保其正确性和可靠性。
- 可能引入错误:如果代理的实现不正确或存在缺陷,可能会导致意外的行为或错误。需要仔细测试和验证代理的逻辑以确保其按预期工作。
五、代理模式的使用场景
Java代理模式在以下场景中的应用:
1. 日志的采集
通过代理模式,我们可以在方法调用前后添加日志记录的逻辑,而无需修改原始类的代码。这有助于跟踪方法的执行情况、性能分析等。
2. 权限控制
在访问敏感资源或执行关键操作时,可以使用代理模式来拦截方法调用并进行权限检查。如果权限不足,则拒绝执行原方法,并返回相应的错误信息。
3. 实现AOP(面向切面编程)
AOP是代理模式的一种高级应用。通过动态代理,我们可以在不修改原始类代码的情况下,为方法调用添加横切关注点,如日志记录、事务管理、安全检查等。Spring AOP就是基于代理模式实现的。
4. MyBatis Mapper
MyBatis使用动态代理生成Mapper接口的实现类。当你调用Mapper接口的方法时,实际上是调用了一个动态生成的代理对象,该对象会根据方法签名和配置信息执行相应的SQL操作。
5. Spring的事务管理
Spring通过AOP和代理模式实现了声明式事务管理。当我们在方法上添加@Transactional注解时,Spring会为该方法创建一个代理对象,并在代理对象中添加事务管理的逻辑。这样,我们就可以通过调用代理对象来自动管理事务,而无需在代码中显式编写事务管理的代码。
6. 全局捕获异常
通过代理模式,我们可以在方法调用前后添加异常处理的逻辑。当方法抛出异常时,代理对象可以捕获该异常并进行相应的处理,如记录日志、返回统一的错误信息等。这有助于实现全局的异常处理策略。
7. RPC远程调用接口
在RPC框架中,客户端通常不会直接调用远程服务的方法,而是通过调用一个本地代理对象来实现远程调用。这个代理对象负责将方法调用转换为网络请求,并发送给远程服务。远程服务执行完毕后,将结果返回给代理对象,代理对象再将结果返回给客户端。这种方式隐藏了远程调用的复杂性,使得客户端可以像调用本地方法一样调用远程服务。
8. 分布式事务原理代理数据源
在分布式系统中,为了实现跨多个服务或数据库的事务一致性,我们可以使用分布式事务解决方案(如XA事务、TCC事务等)。这些解决方案通常会提供一个代理数据源或代理连接池,用于拦截和管理数据库操作。当应用程序访问数据库时,实际上是访问了这个代理数据源。代理数据源会根据分布式事务的配置和执行情况来决定是否提交或回滚事务操作。这种方式可以在不修改应用程序代码的情况下实现分布式事务的管理和协调。
六、代理模式的三种实现
6.1 静态代理模式
Java中的静态代理模式是一种相对简单的设计模式,它要求代理类和被代理类实现相同的接口或继承自相同的父类。代理类在内部持有被代理类的引用,并在需要时调用被代理类的方法,同时可以在调用前后添加额外的逻辑。

下面是一个简单的静态代理模式的实现:
首先,定义一个接口:
public interface Service {void performTask();
}
然后,创建被代理类,实现该接口:
public class RealService implements Service {@Overridepublic void performTask() {System.out.println("RealService is performing the task.");}
}
接下来,创建代理类,同样实现该接口,并在构造函数中接收一个被代理类的实例:
public class ProxyService implements Service {private final Service realService;public ProxyService(Service realService) {this.realService = realService;}@Overridepublic void performTask() {System.out.println("ProxyService: Before task.");realService.performTask(); // 调用被代理类的方法System.out.println("ProxyService: After task.");}
}
最后,在客户端代码中使用代理类:
public class Client {public static void main(String[] args) {// 创建被代理对象Service realService = new RealService();// 创建代理对象,将被代理对象作为参数传入Service proxyService = new ProxyService(realService);// 通过代理对象执行方法,会触发代理类中的额外逻辑proxyService.performTask();}
}
当运行客户端代码时,输出将会是:
ProxyService: Before task.
RealService is performing the task.
ProxyService: After task.
在这个例子中,ProxyService是代理类,它增强了RealService的功能,即在执行任务前后输出了额外的日志信息。客户端代码通过代理类ProxyService来调用performTask方法,而不需要直接与被代理类RealService交互。这种方式允许在不修改原始类的情况下增加新的行为或控制访问。
6.2 JDK动态代理的实现

JDK动态代理是Java提供的一种在运行时创建代理类和对象的方式。它主要利用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。下面是一个使用JDK动态代理模式的实现:
首先,定义一个接口:
public interface Service {void performTask();
}
然后,创建被代理类,实现该接口:
public class RealService implements Service {@Overridepublic void performTask() {System.out.println("RealService is performing the task.");}
}
接下来,创建一个实现了InvocationHandler接口的类。这个类的invoke方法会在代理对象的方法被调用时被执行:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class ServiceInvocationHandler implements InvocationHandler {private final Object target;public ServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before invoking method: " + method.getName());Object result = method.invoke(target, args); // 调用被代理对象的方法System.out.println("After invoking method: " + method.getName());return result;}
}
最后,在客户端代码中使用Proxy.newProxyInstance方法创建代理对象,并通过该代理对象调用方法:
import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {// 创建被代理对象Service realService = new RealService();// 创建InvocationHandler实例,将被代理对象传入InvocationHandler handler = new ServiceInvocationHandler(realService);// 使用Proxy.newProxyInstance创建代理对象Service proxyService = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), // 类加载器new Class<?>[] { Service.class }, // 代理类要实现的接口列表handler // 关联调用处理器);// 通过代理对象执行方法,会触发InvocationHandler中的invoke方法proxyService.performTask();}
}
当运行客户端代码时,输出将会是:
Before invoking method: performTask
RealService is performing the task.
After invoking method: performTask
在这个例子中,ServiceInvocationHandler是实现了InvocationHandler接口的调用处理器。当通过代理对象proxyService调用performTask方法时,实际上会调用ServiceInvocationHandler中的invoke方法。在invoke方法内部,我们可以添加任何额外的逻辑,比如方法调用前后的日志输出、权限检查等。通过method.invoke(target, args)语句,我们实际上是在调用被代理对象realService的performTask方法。
6.3 Cglib代理
cglib 是一个强大的、高性能的、高质量的代码生成库,它可以在运行时为 Java 类或接口生成子类或代理类。在 Java 代理模式中,当需要代理的类没有实现接口时,可以使用 cglib 来创建一个该类的子类作为代理。
要使用 cglib,首先需要将其添加到项目的依赖中。如果你使用 Maven,可以在 pom.xml 文件中添加以下依赖:
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version> <!-- 请检查是否有更新的版本 -->
</dependency>
下面是一个使用 cglib 创建代理类的示例:
首先,定义一个普通的类(注意,这个类没有实现任何接口):
public class RealService {public void performTask() {System.out.println("RealService is performing the task.");}
}
然后,创建一个实现了 MethodInterceptor 接口的类,该类将用于拦截对代理类方法的调用:
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class ServiceMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before invoking method: " + method.getName());Object result = proxy.invokeSuper(obj, args); // 调用父类(被代理类)的方法System.out.println("After invoking method: " + method.getName());return result;}
}
最后,在客户端代码中使用 Enhancer 类来创建代理对象:
import net.sf.cglib.proxy.Enhancer;public class Client {public static void main(String[] args) {// 创建被代理对象,实际上这里并不需要直接创建,因为cglib会创建它的子类// RealService realService = new RealService();// 创建Enhancer实例,并设置父类为RealServiceEnhancer enhancer = new Enhancer();enhancer.setSuperclass(RealService.class);// 设置回调,即方法拦截器enhancer.setCallback(new ServiceMethodInterceptor());// 创建代理对象RealService proxyService = (RealService) enhancer.create();// 通过代理对象执行方法,会触发ServiceMethodInterceptor中的intercept方法proxyService.performTask();}
}
当运行客户端代码时,输出将会是:
Before invoking method: performTask
RealService is performing the task.
After invoking method: performTask
在这个例子中,ServiceMethodInterceptor 实现了 MethodInterceptor 接口,用于拦截对代理类方法的调用。在 intercept 方法中,我们可以添加任何额外的逻辑,比如方法调用前后的日志输出。通过 proxy.invokeSuper(obj, args) 语句,我们实际上是在调用被代理类 RealService 的 performTask 方法。Enhancer 类用于创建代理类,并通过 create 方法实例化代理对象。
6.4 三种实现的区别和优缺点
代理模式主要有三种实现方式(静态代理、JDK动态代理和cglib动态代理)中由于静态代理通常针对每个具体类编写,不具有通用性,因此这里主要讨论JDK动态代理和cglib动态代理的区别和优缺点。
6.4.1 JDK动态代理
实现方式:
JDK动态代理要求目标类必须实现至少一个接口。代理类是在运行时动态生成的,实现了目标类所实现的所有接口,并通过反射调用目标类的方法。
优点:
- 无需为每个目标类编写具体的代理类,提高了代码的复用性和可维护性。
- 由于代理类实现了接口,因此系统的耦合度较低,更加灵活。
缺点:
- 目标类必须实现至少一个接口,否则无法使用JDK动态代理。
- 在方法调用频繁的情况下,由于使用了反射机制,性能可能较低。
6.4.2 cglib动态代理
实现方式:
cglib动态代理是通过生成目标类的子类来实现的。它不需要目标类实现任何接口,而是通过继承目标类并重写其方法来创建代理类。在方法调用时,通过方法拦截器来增强方法的调用。
优点:
- 目标类无需实现任何接口,更加灵活。
- 在某些场景下,由于直接调用子类方法而无需经过反射,性能可能优于JDK动态代理。
缺点:
- 由于代理类是通过继承目标类来实现的,因此目标类和方法不能声明为final类型。
- 引入了额外的cglib库依赖,增加了项目的复杂性。
- 系统的耦合度可能较高,因为代理类与目标类是继承关系。
JDK动态代理和cglib动态代理各有优缺点,选择哪种方式取决于具体的需求和场景。如果目标类已经实现了接口,那么JDK动态代理是一个不错的选择。如果目标类没有实现接口,或者需要更高的性能,那么可以考虑使用cglib动态代理。不过,在使用cglib时需要注意目标类和方法不能声明为final类型,以及引入额外依赖的问题。
七、注意事项
- 选择合适的代理类型:根据具体需求选择合适的代理类型(如远程代理、虚拟代理等),并确保代理的实现与抽象角色一致。
- 控制代理的复杂性:尽量保持代理类的简洁和清晰,避免引入不必要的复杂性。只在需要时添加额外的功能或操作。
- 注意线程安全问题:如果代理在多线程环境中使用,需要确保它是线程安全的。考虑使用同步机制或线程本地存储来避免竞态条件和数据不一致问题。
- 测试代理的逻辑:仔细测试和验证代理的逻辑以确保其按预期工作。特别关注代理与真实对象之间的交互和边界情况处理。
总结
Java代理模式是一种强大的设计模式,它允许我们通过代理类来控制对原始对象的访问。无论是静态代理还是动态代理,它们都为我们提供了增加额外逻辑、隐藏复杂性以及提高系统可扩展性的能力。在实际开发中,合理地运用代理模式可以使我们的代码更加灵活、可维护。
相关文章:
Java设计模式:代理模式的静态和动态之分(八)
码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 ! 在软件设计中,代理模式是一种常用的设计模式,它为我们提供了一种方式来控制对原始对象的访问。在Java中&a…...
【论文通读】AgentStudio: A Toolkit for Building General Virtual Agents
AgentStudio: A Toolkit for Building General Virtual Agents 前言AbstractMotivationFramework评估GUI GroudingReal-World Cross-Application Benchmark Suite Conclusion 前言 来自昆仑万维的一篇智能体环境数据大一统框架工作,对未来计算机智能体的发展具有指…...
wordvect嵌入和bert嵌入的区别
Word2Vec 嵌入和 BERT 嵌入之间有几个关键区别: 训练方式: Word2Vec:Word2Vec 是一个基于神经网络的词嵌入模型,它通过训练一个浅层的神经网络来学习单词的分布式表示。它有两种训练方式:连续词袋模型(CBOW…...
渗透测试练习题解析 5(CTF web)
1、[安洵杯 2019]easy_serialize_php 1 考点:PHP 反序列化逃逸 变量覆盖 【代码审计】 通过 GET 的方式获取参数 f 的值,传递给变量 function 定义一个过滤函数,过滤掉特定字符(用空字符替换) 下面的代码其实没什么用…...
PCA(Principal Component Analysis,主成分分析)
PCA(Principal Component Analysis,主成分分析)是一种在数据分析中广泛应用的统计方法,主要用于数据降维、可视化和去噪。以下是对PCA的发展史、工作原理以及理论基础的详细解释: Principal Component Analysis 一、PC…...
干货 | 探索CUTTag:从样本到文库,实验步步为营!
CUT&Tag(Cleavage Under Targets and Tagmentation)是一种新型DNA-蛋白互作研究技术,主要用于研究转录因子或组蛋白修饰在全基因组上的结合或分布位点。相比于传统的ChIP-seq技术,CUT&Tag反应在细胞内进行,创新…...
提质不增本,降本不降质
#公益巡讲# #质量万里行# 公开课、沙龙活动...
数据结构---顺序表实现
目录 1.顺序表 2.动态顺序表的实现 (4)顺序表初始化 (5)顺序表销毁 (6)顺序表的插入 a.尾插 b.头插 (7)顺序表的删除 a.尾删 b.头删 (8)指定位置之…...
python docx 添加动态表格
在Python中,使用python-docx库可以创建Word文档并添加动态表格。以下是一个简单的例子,演示如何创建一个包含动态内容的表格: from docx import Document# 创建一个Word文档 document Document()# 添加一个标题 document.add_heading(动态表…...
git配置多SSH
目的: 一台电脑可以让github、gitee等账号同时存在,让不同账号配置不同的密钥 第一步:创建不同平台的SSH公钥 执行命令: ssh-keygen -t rsa -C "对应仓库邮箱地址" -f ~/.ssh/id_rsa.github 如果执行上面的命令&…...
IDEA连接SqlServer数据库
目录 下载jar包 下载sqljdbc_12.6压缩包 解压 导入IDEA 新建文件夹 复制粘贴进JDBC文件夹并设为library 编写类及方法 代码 下载jar包 以sqljdbc_12.6为例 下载sqljdbc_12.6压缩包 最新地址:sqljdbc 官方最新地址 解压 解压即用 导入IDEA 新建文件夹 复制…...
LeetCode 378 有序矩阵中第K小的元素
题目信息 LeetoCode地址: . - 力扣(LeetCode) 题解内容大量转载于:. - 力扣(LeetCode) 题目理解 题意很直观,就是求二维矩阵中所有元素排序后第k小的数。 最小堆写法 该写法不再赘述,维护…...
Vue3(domdiff)最长递归子序列求解简易版(超简单)
Vue3(domdiff)最长递归子序列求解简易版 ⚠️ 关键词(每一个都需要理解)js 代码实现写完感想欢迎关注 ⚠️ 关键词(每一个都需要理解) 动态规划(O(N^2))(不提倡…...
LLaMA-Factory+qwen多轮对话微调
LLaMA-Factory地址:https://github.com/hiyouga/LLaMA-Factory/blob/main/README_zh.md qwen地址:https://huggingface.co/Qwen/Qwen-7B-Chat/tree/main 数据准备 数据样例 [ {"id": "x3959", "conversations": [{&qu…...
邦芒面试:如何在面试中巧妙回答自己的缺点
在面试中,被问及自己的缺点时,如何巧妙回答是一门学问。恰当的回答不仅能够展示你的自我认知,还能让面试官看到你的成长潜力和积极态度。 首先,切忌谈一些看似缺点实则优点的话题,如追求完美、待人接物太客气等。这些…...
Android:身份证识别功能实现
说明: 此文使用华为SDK、百度SDK、百度在线API三种方式实现。 一、使用华为SDK实现身份证识别: 说明:免费,不需要联网。 1.AndroidManifest.xml添加权限:<uses-permission android:name"android.permissio…...
MacOS安装Homebrew教程
安装 Homebrew 是在 macOS 上管理软件包的一种简便方法。以下是安装 Homebrew 的步骤: 打开终端:你可以通过在 Spotlight 搜索栏中输入“终端”并按下回车键来打开 macOS 的终端应用程序。 执行安装命令:在终端中粘贴以下命令并按下回车键执…...
laravel如何通过DB获取一条数据并转成数组
在 Laravel 中,你可以使用原生数据库查询构建器(DB facade)来获取一条数据,并将其转换为数组。这可以通过在查询链的末尾调用 first() 方法后,使用 toArray() 方法来实现。first() 方法会返回一个 StdClass 对象&#…...
ENSP USG防火墙接入虚拟机;开启Web访问;
1.添加防火墙及云,启动防火墙; 2.配置桥接网卡; 默认账户:admin 默认密码:Admin123 #第一次登陆需修改密码; 默认G0/0/0口为管理口,而在模拟器中进入防火墙的web需如下配置: 配置 …...
数据结构算法题(力扣)——链表
以下题目建议大家先自己动手练习,再看题解代码。这里只提供一种做法,可能不是最优解。 1. 移除链表元素(OJ链接) 题目描述:给一个链表的头节点 head 和一个整数 val ,删除链表中所有满足值等于 val 的节点…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
Axure 下拉框联动
实现选省、选完省之后选对应省份下的市区...
Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
