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

java基础之代理

代理模式(Proxy Pattern)

简介
  • 是一种结构型设计模式,主要用于为某对象提供一个代理对象,以控制对该对象的访问。
  • 通过引入一个代理对象来控制对原对象的访问。代理对象在客户端和目标对象之间充当中介,负责将客户端的请求转发给目标对象,同时可以在转发请求前后进行额外的处理(如权限控制、延迟加载、日志记录等)而不修改目标对象的代码。
  • 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
元素
  • 抽象主题(Subject):定义了真实主题和代理主题的共同接口,这样在任何使用真实主题的地方都可以使用代理主题。
  • 真实主题(Real Subject):实现了抽象主题接口,是代理对象所代表的真实对象。客户端直接访问真实主题,但在某些情况下,可以通过代理主题来间接访问。
  • 代理(Proxy):实现了抽象主题接口,并持有对真实主题的引用。代理主题通常在真实主题的基础上提供一些额外的功能,例如延迟加载、权限控制、日志记录等。
  • 客户端(Client):使用抽象主题接口来操作真实主题或代理主题,不需要知道具体是哪一个实现类。
类型
  • 静态代理(Static Proxy):代理类在编译时就已经确定,代理类与目标类实现相同的接口。
  • 动态代理(Dynamic Proxy):代理类在运行时动态生成,通常使用 Java 的 java.lang.reflect.Proxy 或 CGLIB 库来实现。
  • 保护代理(Protection Proxy):控制对目标对象的访问权限。
  • 虚拟代理(Virtual Proxy):通过代理对象来延迟对真实对象的创建或初始化。
  • 缓存代理(Cache Proxy):通过代理对象在一定时间内缓存目标对象的结果,从而提升性能。
优点
  • 职责分离:代理模式将访问控制与业务逻辑分离。
  • 扩展性:可以灵活地添加额外的功能或控制。
  • 智能化:可以智能地处理访问请求,如延迟加载、缓存等。
缺点
  • 性能开销:增加了代理层可能会影响请求的处理速度。
  • 实现复杂性:某些类型的代理模式实现起来可能较为复杂。
静态代理

静态代理是一种在编译期就确定的代理模式。代理类需要实现与目标类相同的接口,客户端通过代理类调用目标对象的方法。静态代理通常用于在方法调用前后添加额外操作,比如日志记录、安全检查等。

动态代理

动态代理是在运行时动态生成代理类,而不是在编译时生成。动态代理的优势是减少了重复的代理类代码,并且能够在运行时灵活地处理方法调用。

jdk动态代理和cglib动态代理
JDK动态代理CGLIB动态代理
代理对象必须实现接口不需要实现接口
代理方式基于接口和反射基于字节码生成子类
性能创建代理开销小,方法调用开销较高创建代理开销大,方法调用性能较好
限制不能代理没有接口的类不能代理final类和final方法
使用场景适用于接口驱动的开发适用于没有接口的类
spring AOP默认接口时使用JDK动态代理没有接口时使用CGLIB动态代理

代码示例

静态代理
interface Subject {void doAction();
}class RealSubject implements Subject {@Overridepublic void doAction() {System.out.println("doAction in RealSubject.");}
}class MyProxy implements Subject {private RealSubject realSubject;public MyProxy(RealSubject realSubject) {this.realSubject = realSubject;}@Overridepublic void doAction() {System.out.println("Before doing action.");realSubject.doAction();System.out.println("After doing action.");}
}public class StaticProxyExample {public static void main(String[] args) {RealSubject realSubject = new RealSubject();MyProxy myProxy = new MyProxy(realSubject);myProxy.doAction();}
}
JDK动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface Subject {void doAction();
}class RealSubject implements Subject {@Overridepublic void doAction() {System.out.println("doAction in RealSubject.");}
}class MyInvocationHandler implements InvocationHandler {private final Object realSubject;public MyInvocationHandler(Object realSubject) {this.realSubject = realSubject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before doing action.");Object result = method.invoke(realSubject, args);System.out.println("After doing action.");return result;}
}public class DynamicProxyExample {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Subject subject = (Subject) Proxy.newProxyInstance(RealSubject.class.getClassLoader(),new Class[]{Subject.class},new MyInvocationHandler(realSubject));subject.doAction();}
}
cglib动态代理
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;class RealSubject {public void doAction() {System.out.println("doAction in RealSubject.");}
}class MyProxy implements MethodInterceptor {private Object target;public MyProxy(Object target) {this.target = target;}public Object getProxyInstance() {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before doing action.");Object result = proxy.invokeSuper(obj, args);System.out.println("Before doing action.");return result;}
}public class StaticProxyExample {public static void main(String[] args) {RealSubject realSubject = new RealSubject();MyProxy proxy = new MyProxy(realSubject);RealSubject proxyService = (RealSubject) proxy.getProxyInstance();proxyService.doAction();}
}

相关文章:

java基础之代理

代理模式&#xff08;Proxy Pattern&#xff09; 简介 是一种结构型设计模式&#xff0c;主要用于为某对象提供一个代理对象&#xff0c;以控制对该对象的访问。通过引入一个代理对象来控制对原对象的访问。代理对象在客户端和目标对象之间充当中介&#xff0c;负责将客户端的…...

计算机网络——期末复习(6)期末考试样例2(含答案)

一、单项选择题(每题1分&#xff0c;共10小题&#xff0c;共计10分) 1.因特网多播采用的管理协议是( )协议。 A.UDP B.BGP C.IGMP D.TCP 2.采用CIDR时&#xff0c;某计算机的IP地址是202.35.79.88/19&#xff0c;该计算机所处子网的地址是( )。 A.202.35.0.…...

JavaScript 获取DOM对象

html的标签被js获取到之后就变成了js对象&#xff0c;对象里面包含了标签的属性和方法 。同一时间获取多个对象则会翻译一个数组&#xff0c;数组元素是对象 获取方法 1. const a document.getElementById("id")&#xff0c;根据标签的id来获取。因为id是唯一的、…...

一文讲明白朴素贝叶斯算法及其计算公式(入门普及)

1、贝叶斯算法 贝叶斯定理由英国数学家托马斯贝叶斯 ( Thomas Bayes) 提出的&#xff0c;用来描述两个条件概率之间的关系。通常&#xff0c;事件A在事件B 发生的条件下与事件 B 在事件 A 发生的条件下&#xff0c;它们两者的概率并不相同&#xff0c;但是它们两者之间存在一定…...

实际开发中,常见pdf|word|excel等文件的预览和下载

实际开发中,常见pdf|word|excel等文件的预览和下载 背景相关类型数据之间的转换1、File转Blob2、File转ArrayBuffer3、Blob转ArrayBuffer4、Blob转File5、ArrayBuffer转Blob6、ArrayBuffer转File 根据Blob/File类型生成可预览的Base64地址基于Blob类型的各种文件的下载各种类型…...

Python自学 - 递归函数

1 Python自学 - 递归函数 递归函数是一种在函数体内调用自己的函数&#xff0c;就像“左脚踩着右脚&#xff0c;再右脚踩着左脚… 嗯&#xff0c;你就可以上天了&#xff01;”。递归函数虽然不能上天&#xff0c;但在处理某些场景时非常好用&#xff0c; 一种典型的场景就是遍…...

Spark-Streaming有状态计算

一、上下文 《Spark-Streaming初识》中的NetworkWordCount示例只能统计每个微批下的单词的数量&#xff0c;那么如何才能统计从开始加载数据到当下的所有数量呢&#xff1f;下面我们就来通过官方例子学习下Spark-Streaming有状态计算。 二、官方例子 所属包&#xff1a;org.…...

Markdown如何导出Html文件Markdown文件

Markdown如何导出Html文件Markdown文件 前言语法详解小结其他文章快来试试吧☺️ Markdown 导出 HTML &#x1f448;点击这里也可查看 前言 Markdown的源文件以md为后缀。Markdown是HTML语法的简化版本&#xff0c;它本身不带有任何样式信息。我们所看到的Markdown网页(如&…...

使用Python进行图像裁剪和直方图分析

一、简介 在数字图像处理领域&#xff0c;裁剪和分析图像的直方图是两个非常基本且重要的操作。本文将通过一个简单的Python项目&#xff0c;展示如何使用skimage和matplotlib库来裁剪图像并分析其RGB通道的直方图。 二、环境准备 在开始之前&#xff0c;请确保你已经安装了以…...

企业内管信息化系统

本文结尾处获取源码。 本文结尾处获取源码。 本文结尾处获取源码。 一、相关技术 后端&#xff1a;Java、JavaWeb / Springboot。前端&#xff1a;Vue、HTML / CSS / Javascript 等。数据库&#xff1a;MySQL 二、相关软件&#xff08;列出的软件其一均可运行&#xff09; I…...

【python因果库实战15】因果生存分析4

这里写目录标题 加权标准化生存分析总结个体层面的生存曲线 加权标准化生存分析 我们还可以将加权与标准化结合起来&#xff0c;使用 WeightedStandardizedSurvival 模块。在这里&#xff0c;我们将逆倾向得分加权模型&#xff08;根据基线协变量重新加权人群&#xff09;与加…...

Linux 线程详解

目录 一、线程概述 二、线程创建 三、线程终止 四、线程回收 五、线程取消 六、线程分离 七、线程安全 一、线程概述 线程是进程内的一个执行单元&#xff0c;是进程内可调度的实体。一个进程可以包含多个线程&#xff0c;这些线程共享进程的资源&#xff0c;如内存空…...

云架构:考量与框架

云架构&#xff1a;考量与框架 引言 在当今的数字化环境中&#xff0c;云计算已成为现代商业运营的基石。一个设计良好的云架构框架为可扩展、安全和弹性的系统奠定了基础。本文将深入探讨云架构的核心要素&#xff0c;讨论重要的考量因素、设计指南&#xff0c;以及最佳实践…...

SD下载、安装、使用、卸载-Stable Diffusion整合包v4.10发布!

目录 前言概述 SD安装1、安装软件2、启动3、配置4、运行5、测试 导入SD模型【决定画风】常用模型下载安装模型 SD卸载SD文生图提示词提示词使用技巧提示词的高级使用技巧强调关键词 前言 我向来不喜欢搞一些没有用的概念&#xff0c;所以直接整理可能用到的东西。 sd简单的说…...

java 发送邮件

前期准备 pom文件中引入 JavaMail API 和 JavaBean Activation FrameWork&#xff0c;得到两个jar包&#xff1a;mail.jar 和 activation.jar 发送简单邮件&#xff08;只有邮件正文&#xff0c;普通文本&#xff09; package com.zbttest.email;import com.sun.mail.util.Ma…...

聚类系列 (二)——HDBSCAN算法详解

在进行组会汇报的时候&#xff0c;为了引出本研究动机&#xff08;论文尚未发表&#xff0c;暂不介绍&#xff09;&#xff0c;需要对DBSCAN、OPTICS、和HDBSCAN算法等进行详细介绍。在查询相关资料的时候&#xff0c;发现网络上对于DBSCAN算法的介绍非常多与细致&#xff0c;但…...

AngularJS HTML DOM

关于《AngularJS HTML DOM》的文章&#xff0c;我找到了一些有用的信息。这篇文章主要介绍了AngularJS如何通过特定的指令与HTML DOM元素进行交互。以下是一些关键点&#xff1a; ng-disabled 指令&#xff1a;这个指令用于将应用程序数据绑定到HTML的disabled属性。例如&#…...

C语言延时实现

C语言延时实现 在C语言中&#xff0c;delay 函数通过空循环实现延时&#xff0c;而不是像其他高级语言&#xff08;如Python&#xff09;直接使用 sleep 函数。这种实现方式是基于单片机的特性和C语言的底层操作。下面详细解释为什么这种空循环可以实现延时&#xff0c;以及它…...

OSI模型的网络层中产生拥塞的主要原因?

&#xff08; 1 &#xff09;缓冲区容量有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 2 &#xff09;传输线路的带宽有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 3 &#xff09;网络结点的处理能力有限&#xff1b;&#xff08; 1 分…...

机器学习周报-ModernTCN文献阅读

文章目录 摘要Abstract 0 提升有效感受野&#xff08;ERF&#xff09;1 相关知识1.1 标准卷积1.2 深度分离卷积&#xff08;Depthwise Convolution&#xff0c;DWConv&#xff09;1.3 逐点卷积&#xff08;Pointwise Convolution&#xff0c;PWConv&#xff09;1.4 组卷积(Grou…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...