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基础之代理
代理模式(Proxy Pattern) 简介 是一种结构型设计模式,主要用于为某对象提供一个代理对象,以控制对该对象的访问。通过引入一个代理对象来控制对原对象的访问。代理对象在客户端和目标对象之间充当中介,负责将客户端的…...
计算机网络——期末复习(6)期末考试样例2(含答案)
一、单项选择题(每题1分,共10小题,共计10分) 1.因特网多播采用的管理协议是( )协议。 A.UDP B.BGP C.IGMP D.TCP 2.采用CIDR时,某计算机的IP地址是202.35.79.88/19,该计算机所处子网的地址是( )。 A.202.35.0.…...
JavaScript 获取DOM对象
html的标签被js获取到之后就变成了js对象,对象里面包含了标签的属性和方法 。同一时间获取多个对象则会翻译一个数组,数组元素是对象 获取方法 1. const a document.getElementById("id"),根据标签的id来获取。因为id是唯一的、…...
一文讲明白朴素贝叶斯算法及其计算公式(入门普及)
1、贝叶斯算法 贝叶斯定理由英国数学家托马斯贝叶斯 ( Thomas Bayes) 提出的,用来描述两个条件概率之间的关系。通常,事件A在事件B 发生的条件下与事件 B 在事件 A 发生的条件下,它们两者的概率并不相同,但是它们两者之间存在一定…...
实际开发中,常见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自学 - 递归函数 递归函数是一种在函数体内调用自己的函数,就像“左脚踩着右脚,再右脚踩着左脚… 嗯,你就可以上天了!”。递归函数虽然不能上天,但在处理某些场景时非常好用, 一种典型的场景就是遍…...
Spark-Streaming有状态计算
一、上下文 《Spark-Streaming初识》中的NetworkWordCount示例只能统计每个微批下的单词的数量,那么如何才能统计从开始加载数据到当下的所有数量呢?下面我们就来通过官方例子学习下Spark-Streaming有状态计算。 二、官方例子 所属包:org.…...
Markdown如何导出Html文件Markdown文件
Markdown如何导出Html文件Markdown文件 前言语法详解小结其他文章快来试试吧☺️ Markdown 导出 HTML 👈点击这里也可查看 前言 Markdown的源文件以md为后缀。Markdown是HTML语法的简化版本,它本身不带有任何样式信息。我们所看到的Markdown网页(如&…...
使用Python进行图像裁剪和直方图分析
一、简介 在数字图像处理领域,裁剪和分析图像的直方图是两个非常基本且重要的操作。本文将通过一个简单的Python项目,展示如何使用skimage和matplotlib库来裁剪图像并分析其RGB通道的直方图。 二、环境准备 在开始之前,请确保你已经安装了以…...
企业内管信息化系统
本文结尾处获取源码。 本文结尾处获取源码。 本文结尾处获取源码。 一、相关技术 后端:Java、JavaWeb / Springboot。前端:Vue、HTML / CSS / Javascript 等。数据库:MySQL 二、相关软件(列出的软件其一均可运行) I…...
【python因果库实战15】因果生存分析4
这里写目录标题 加权标准化生存分析总结个体层面的生存曲线 加权标准化生存分析 我们还可以将加权与标准化结合起来,使用 WeightedStandardizedSurvival 模块。在这里,我们将逆倾向得分加权模型(根据基线协变量重新加权人群)与加…...
Linux 线程详解
目录 一、线程概述 二、线程创建 三、线程终止 四、线程回收 五、线程取消 六、线程分离 七、线程安全 一、线程概述 线程是进程内的一个执行单元,是进程内可调度的实体。一个进程可以包含多个线程,这些线程共享进程的资源,如内存空…...
云架构:考量与框架
云架构:考量与框架 引言 在当今的数字化环境中,云计算已成为现代商业运营的基石。一个设计良好的云架构框架为可扩展、安全和弹性的系统奠定了基础。本文将深入探讨云架构的核心要素,讨论重要的考量因素、设计指南,以及最佳实践…...
SD下载、安装、使用、卸载-Stable Diffusion整合包v4.10发布!
目录 前言概述 SD安装1、安装软件2、启动3、配置4、运行5、测试 导入SD模型【决定画风】常用模型下载安装模型 SD卸载SD文生图提示词提示词使用技巧提示词的高级使用技巧强调关键词 前言 我向来不喜欢搞一些没有用的概念,所以直接整理可能用到的东西。 sd简单的说…...
java 发送邮件
前期准备 pom文件中引入 JavaMail API 和 JavaBean Activation FrameWork,得到两个jar包:mail.jar 和 activation.jar 发送简单邮件(只有邮件正文,普通文本) package com.zbttest.email;import com.sun.mail.util.Ma…...
聚类系列 (二)——HDBSCAN算法详解
在进行组会汇报的时候,为了引出本研究动机(论文尚未发表,暂不介绍),需要对DBSCAN、OPTICS、和HDBSCAN算法等进行详细介绍。在查询相关资料的时候,发现网络上对于DBSCAN算法的介绍非常多与细致,但…...
AngularJS HTML DOM
关于《AngularJS HTML DOM》的文章,我找到了一些有用的信息。这篇文章主要介绍了AngularJS如何通过特定的指令与HTML DOM元素进行交互。以下是一些关键点: ng-disabled 指令:这个指令用于将应用程序数据绑定到HTML的disabled属性。例如&#…...
C语言延时实现
C语言延时实现 在C语言中,delay 函数通过空循环实现延时,而不是像其他高级语言(如Python)直接使用 sleep 函数。这种实现方式是基于单片机的特性和C语言的底层操作。下面详细解释为什么这种空循环可以实现延时,以及它…...
OSI模型的网络层中产生拥塞的主要原因?
( 1 )缓冲区容量有限;( 1.5 分) ( 2 )传输线路的带宽有限;( 1.5 分) ( 3 )网络结点的处理能力有限;( 1 分…...
机器学习周报-ModernTCN文献阅读
文章目录 摘要Abstract 0 提升有效感受野(ERF)1 相关知识1.1 标准卷积1.2 深度分离卷积(Depthwise Convolution,DWConv)1.3 逐点卷积(Pointwise Convolution,PWConv)1.4 组卷积(Grou…...
创新实训博客记录 | 2.用户模块实现(登录/个人信息等)
目录 1. 技术实现思路 2. 目前已实现接口 3. 关键业务流程说明 3.1 登录流程 3.2 个人资料与角色 3.3 用户、患者、医生关系 4. 总结 本周主要推进了后端的用户模块,进入到“可登录、可鉴权、可管理基础人员信息”的阶段。 当前已经完成用户认证、个人信息、…...
Linux I-O 模型深入理解
Linux I/O 模型深入理解:解锁高性能的关键 在当今高并发的网络环境中,Linux系统的I/O模型是支撑高性能服务的核心机制之一。无论是Web服务器、数据库还是实时通信系统,其底层I/O处理效率直接决定了系统的吞吐量和响应速度。理解Linux I/O模型…...
SmallThinker-3B部署教程:适配低显存设备的开源大模型轻量化方案
SmallThinker-3B部署教程:适配低显存设备的开源大模型轻量化方案 专为资源受限环境设计的智能助手,让每个人都能轻松用上大模型 1. 环境准备与快速部署 SmallThinker-3B-Preview是一个基于Qwen2.5-3b-Instruct微调而来的轻量级模型,专门为边…...
黄仁勋可能开始焦虑了
只做卖铲人,已经不能让 Nvidia 高枕无虞了。 2026年4月15日,黄仁勋在Dwarkesh Patel 的播客里经历了一场他很久没经历过的尖锐追问。一个多小时的对话,他反复用来定义英伟达的那句话是:“必须有东西把电子变成token。”他把自家公…...
告别QML资源路径噩梦:手把手教你用Prefix和别名管理图片资源(附避坑指南)
告别QML资源路径噩梦:手把手教你用Prefix和别名管理图片资源(附避坑指南) 在Qt Quick的UI开发中,资源路径管理往往是开发者最容易忽视却又最常踩坑的环节。想象一下这样的场景:你的QML文件中散落着各种source: "…...
Qwen3-TTS开源语音模型快速上手指南:97ms低延迟流式生成实操
Qwen3-TTS开源语音模型快速上手指南:97ms低延迟流式生成实操 本文介绍如何快速上手Qwen3-TTS语音合成模型,重点演示其97ms超低延迟的流式生成能力,让你在10分钟内掌握从安装到实际使用的完整流程。 1. 环境准备与快速部署 Qwen3-TTS是一个强…...
别再问多少钱一公里了!手把手教你拆解无人机倾斜摄影建模的真实成本(附Smart3D/DP-Smart实战避坑)
无人机倾斜摄影建模成本全解析:从设备选型到项目落地的实战指南 "一平方公里1万元"的行业报价标准究竟靠不靠谱?这个问题困扰着无数初次接触倾斜摄影技术的项目决策者。作为从业八年的三维建模技术顾问,我必须指出:任何…...
Obsidian PDF++插件技术架构:实现原生PDF标注与知识图谱集成
Obsidian PDF插件技术架构:实现原生PDF标注与知识图谱集成 【免费下载链接】obsidian-pdf-plus PDF: the most Obsidian-native PDF annotation & viewing tool ever. Comes with optional Vim keybindings. 项目地址: https://gitcode.com/gh_mirrors/ob/obs…...
从静态到动态:深度解析shields.io徽章生成与Git平台项目美化实战
1. 为什么你的开源项目需要徽章? 第一次在GitHub上看到那些花花绿绿的小徽章时,我完全没意识到它们的重要性。直到自己的项目star数一直上不去,才发现专业的第一印象有多关键。这些看似简单的彩色标签,实际上是项目的"数字名…...
Dify二次开发实战:从环境搭建到CI/CD全链路解析
1. 环境准备:搭建Dify二次开发的基础设施 第一次接触Dify二次开发时,我被它复杂的依赖关系搞得手忙脚乱。经过三个项目的实战积累,我总结出一套最稳定的环境配置方案,让你少走弯路。 开发Dify需要同时处理Python和Node.js两个生态…...
