设计模式——代理模式
导航:
【黑马Java笔记+踩坑汇总】JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud+黑马旅游+谷粒商城+学成在线+设计模式+牛客面试题
目录
1、代理模式的基本介绍
2、静态代理
3、JDK动态代理
4、Cglib 代理
5、代理模式 的变体(应用场景)
1、代理模式的基本介绍
代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象
代理模式是结构型设计模式(用于描述对象之间的组合关系)。
好处:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能
被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象(代理时对目标对象进行安全控制)
我们并不希望客户端直接调用目标对象,而是通过代理对象对目标对象实现安全控制或增强功能。所以我们客户端直接依赖代理对象,代理对象依赖目标对象:

代理模式有不同的形式,主要有三种:静态代理、JDK动态代理、Cglib 代理
静态代理:
目标对象与代理对象实现租同的接口或继承相同的父类,在编译时生成代理对象。
目标对象实现代理接口,代理对象实现并聚合代理接口,重写方法编写增强后逻辑。
JDK动态代理:
通过Java反射机制在运行时动态地在内存中生成代理对象。 目标对象需要实现代理接口。
目标对象实现代理接口,代理工厂通过Proxy类的静态方法newProxyInstance(),利用反射机制返回代理对象实例。
newProxyInstance()三个参数:目标对象的类加载器、目标对象的接口、实现InvocationHandler接口并重写invoke()方法,编写代理对象逻辑。
应用:Spring AOP采用了动态代理的方式,在运行时动态的创建代理对象来实现增强。
Cglib 代理:
在内存中构建一个子类对象从而实现对目标对象功能扩展。目标对象不需要实现代理接口。底层是通过使用ASM框架转换字节码并生成新的类。
代理工厂类实现MethodInterceptor接口并重写intercept()方法编写代理逻辑,通过cglib包的Enhancer类设置父类字节码文件和创建子类对象来返回代理对象实例。
ASM框架是一个强大的Java字节码操作框架,可以让程序员通过代码生成和转换现有字节码来操作Java类。ASM可以直接生成字节码,也可以通过访问现有字节码来修改它。
2、静态代理
静态代理在使里时,需要定义接口或者父类,目标对象与代理对象实现租同的接口或继承相同的父类。
实现方式:目标对象实现代理接口,代理对象实现并聚合代理接口,重写方法编写增强后逻辑。
优缺点
- 优点:在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
- 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类。耦合性较高,一旦接口增加方法,目标对象与代理对象都要维护
案例
- 1)定义一个接口:ITeacherDao
- 2)目标对象TeacherDao实现接口ITeacherDao
- 3)使用静态代理方式,就需要在代理对象TeacherDaoProxy中也实现ITeacherDao
- 4)调用的时候通过调用代理对象的方法来调用目标对象
- 5)特别提醒:代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法
UML 类图
核心代码
/*** 代理接口*/ public interface ITeacherDao {void teach(); //代理对象和原始对象重写这个方法 } /*** 目标对象,即被代理对象。实现代理借口*/ public class TeacherDao implements ITeacherDao {@Overridepublic void teach() {System.out.println("老师授课中...");} } /*** 代理对象。实现代理借口*/ public class TeacherDaoProxy implements ITeacherDao {private ITeacherDao iTeacherDao; //接口引用public TeacherDaoProxy(ITeacherDao iTeacherDao) {this.iTeacherDao = iTeacherDao;}@Overridepublic void teach() {System.out.println("准备授课...");iTeacherDao.teach();System.out.println("结束授课...");} }客户端调用代理
//创建被代理对象 TeacherDao teacherDao = new TeacherDao(); //创建代理对象,聚合被代理对象 TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao); //通过代理对象,调用被代理对象的方法 teacherDaoProxy.teach();
3、JDK动态代理
Java中的动态代理是一种机制,它通过在程序运行时动态地生成代理对象,并在代理对象上进行方法调用,实现对目标对象方法的拦截与控制。动态代理是代理设计模式的一种实现方式,与静态代理不同的是,它不需要显示地编写代理类来代理被代理对象,而是通过Java反射机制在运行时动态生成代理类和代理对象。
实现方法:
目标对象实现代理接口,代理工厂通过Proxy类的静态方法newProxyInstance(),利用反射机制返回代理对象实例。
newProxyInstance()三个参数:目标对象的类加载器、目标对象的接口、实现InvocationHandler接口并重写invoke()方法,编写代理对象逻辑。
- 1)代理对象不需要实现接口,但是目标对象要实现接口,否则不能用动态代理
- 2)代理对象的生成,是利用 JDK 的 APl,动态的在内存中构建代理对象
- 3)动态代理也叫做:JDK 代理、接口代理
JDK提供了java.lang.reflect.Proxy类,可以通过它创建基于接口的动态代理对象。使用Proxy类的newProxyInstance静态方法,该方法需要接收三个参数:
static Object newProxylnstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
案例:
核心代码
//代理接口和目标对象同上,目标对象需要实现代理接口 // ITeacherDao与TeacherDao同上 /*** 代理工厂*/ public class TeacherFactory {/*** 目标对象*/private Object target;public TeacherFactory(Object target) {this.target = target;}public Object newProxyInstance() { //1。ClassLoader loader : 指定当前目标对象使用的类加载器,获取加载器的方法固定 //2,Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型 //3。InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法,会把当前执行的目标对象方法作为参数传入return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("JDK代理授课开始...");Object returnVal = method.invoke(target, args);System.out.println("JDK代理授课结束...");return returnVal;}});} }创建代理对象:
//创建目标对象 ITeacherDao target = new TeacherDao(); //给目标对象,创建代理对象,可以转成 ITeacherDao ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance(); // proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象 System.out.println("proxyInstance=" + proxyInstance.getClass()); //通过代理对象,调用目标对象的方法 proxyInstance.teach();其中几个参数
- 1)
ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法固定
- 2)
Class<?>[] interfaces:目标对象实现的接口类型,使用泛型方法确认类型
- 3)
InvocationHandler h:事情处理,执行目标对象的方法时触发事情处理器方法,把当前执行的目标对象方法作为参数传入
4、Cglib 代理
Cglib 代理
静态 代理和 JDK 代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理——这就是 Cglib 代理
Cglib 代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展,有些书也将 Cglib 代理归属到动态代理。
使用方法:
代理工厂类实现MethodInterceptor接口并重写intercept()方法编写代理逻辑,通过cglib包的Enhancer类设置父类字节码文件和创建子类对象来返回代理对象实例。
Cglib包
是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口。它广泛的被许多 AOP 的框架使用,例如 Spring AOP,实现方法拦截。
Cglib 包的底层是通过使用ASM框架来转换字节码并生成新的类
ASM框架
一个强大的Java字节码操作框架,可以让程序员通过代码生成和转换现有字节码来操作Java类。ASM可以直接生成字节码,也可以通过访问现有字节码来修改它。我们可以使用ASM来生成新的类、新的方法、字段、注解等。同时,ASM还允许我们在运行时改变现有的Java类的字节码,从而实现动态的Java类修改,例如添加方法、添加字段等。
在 AOP 编程中如何选择代理模式:
- 目标对象需要实现接口,用 JDK 代理
- 目标对象不需要实现接口,用 Cglib 代理
案例:
- 1)引入
cglib的 jar 文件
- 2)在内存中动态构建子类,注意代理的类不能为
final,否则报错java.lang.IllegalArgumentException
- 3)目标对象的方法如果为
final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法uml图,不再有代理接口
![]()
核心代码
/*** 被代理对象*/ public class TeacherDao {public String teach() {System.out.println("老师授课中...");return "Good";} }/*** 代理工厂类,实现MethodInterceptor 接口*/ public class ProxyFactory implements MethodInterceptor {/*** 目标对象*/private Object target;/*** 构造函数** @param target*/public ProxyFactory(Object target) {this.target = target;}/*** 返回代理对象实例。不是静态方法** @return*/public Object getProxyInstance() {// 1、创建工具类Enhancer enhancer = new Enhancer();// 2、设置父类enhancer.setSuperclass(target.getClass());// 3、设置回调函数enhancer.setCallback(this);// 4、创建子类对象,即代理对象return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("cglib代理开始...");Object retVal = method.invoke(target, args);System.out.println("cglib代理结束...");return retVal;} }调用代理
//创建目标对象 TeacherDao teacherDao = new TeacherDao(); //通过代理工厂创建代理对象 TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(teacherDao).getProxyInstance(); //通过代理对象调用目标对象方法 String retVal = proxyInstance.teach(); System.out.println("retVal=" + retVal);
5、代理模式 的变体(应用场景)
几种常见的代 理模式介绍一几种变体
- 防火墙代理:内网通过代理穿透防火墙,实现对公网的访问
- 缓存代理:比如:当请求图片文件等资源时,先到缓存代理取,如果取到资源则 ok;如果取不到资源,再到公网或者数据库取,然后缓存
- 远程代理:远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息
- 同步代理:主要使用在多线程编程中,完成多线程间同步工作
相关文章:
设计模式——代理模式
导航: 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线设计模式牛客面试题 目录 1、代理模式的基本介绍 2、静态代理 3、JDK动态代理 4、Cglib 代理 5、代理模式 的变体(应用场景) 1、…...
Shiro-721---漏洞复现
漏洞原理 Shiro rememberMe 反序列化远程代码执行漏洞 由于 Apache Shiro cookie 中通过 AES-128-CBC 模式加密的 rememberMe 字段存 在问题,用户可通过 Padding Oracle 加密生成的攻击代码来构造恶意的 rememberMe 字段,并重新请求网站,进…...
Linux【模拟实现C语言文件流】
✨个人主页: 北 海 🎉所属专栏: Linux学习之旅 🎃操作环境: CentOS 7.6 阿里云远程服务器 文章目录 🌇前言🏙️正文1、FILE 结构设计2、函数使用及分析3、文件打开 fopen4、文件关闭 fclose5、缓…...
APK文件结构
文件结构 assets文件用来存放需要打包到Android 应用程序的静态资源文件,例如图片资源文件,JSON配置文件,渠道配置文件,二进制数据文件,HTML5离线资源文件等 与res/raw目录不同的数,assets目录支持任意深度…...
RabbitMQ死信队列延迟交换机
RabbitMQ死信队列&延迟交换机 1.什么是死信 死信&死信队列 死信队列的应用: 基于死信队列在队列消息已满的情况下,消息也不会丢失实现延迟消费的效果。比如:下订单时,有15分钟的付款时间 2. 实现死信队列 2.1 准备E…...
武忠祥老师每日一题||不定积分基础训练(六)
解法一: 求出 f ( x ) , 进而对 f ( x ) 进行积分。 求出f(x),进而对f(x)进行积分。 求出f(x),进而对f(x)进行积分。 令 ln x t , 原式 f ( t ) ln ( 1 e t ) e t 令\ln xt,原式f(t)\frac{\ln (1e^t)}{e^t} 令lnxt,原式f(t)etln(1et) 则 ∫ f ( x ) d…...
C语言结构体详解
结构体是C语言中的一种高级数据类型,它可以将不同的数据类型组合在一起,形成一个自定义的数据类型。结构体为程序员提供了一种组织数据的方式,它为程序开发带来了极大的灵活性和扩展性。 C语言中的结构体定义如下: struct 结构体…...
非盲去模糊简单介绍
文章目录 非盲去模糊简单介绍基于频域的方法1. Wiener滤波器2. 逆滤波器和半正定滤波器 基于空域的方法1. 均值滤波器2. 高斯滤波器3. 双边滤波器 基于偏微分的方法1. 非线性扩散滤波2. 全变分模型3. Laplacian正则化模型 振铃效应应用总结 非盲去模糊简单介绍 非盲去模糊是一…...
C语言动态内存管理与文件操作:打造高效通讯录
本篇博客会讲解如何使用C语言实现一个通讯录。实现通讯录的过程中,会大量用到C语言的知识点,包括但不限于:函数、自定义类型、指针、动态内存管理、文件操作,这些知识点在我的其他博客中都有讲解过,欢迎大家阅读&#…...
2001-2021年全国30省就业人数数据
2001-2021年全国30省就业人数数据/各省就业人数数据 1、时间:2001-2021年 2、范围:包括30个省市不含西藏 3、指标:就业人数 4、来源:各省NJ、社会统计NJ 5、缺失情况说明:无缺失 6、指标说明: 就业人…...
自然语言处理知识抽取(pkuseg、DDParser安装及使用)
一、分词简介 1.基本概念 分词是自然语言处理中的一个重要步骤,它可以帮助我们将文本分成一个个词语,以便更好地理解和分析文本。在计算机视觉、语音识别、机器翻译等领域,分词都扮演着重要的角色。 目前,常用的分词库包括 jie…...
Linux内核面试知识总结
Linux启动过程 1、主机加电自检,加载BIOS硬件信息 2、读取MBR引导文件 3、引导linux内核 4、启动第一个进程init(进程号永远为1) 5、进度相应的运行级别 6、运行终端,输入用户名和密码 linux系统缺省的运行级别 关机、单机…...
深度学习模型压缩与优化加速
1. 简介 深度学习(Deep Learning)因其计算复杂度或参数冗余,在一些场景和设备上限制了相应的模型部署,需要借助模型压缩、系统优化加速、异构计算等方法突破瓶颈,即分别在算法模型、计算图或算子优化以及硬件加速等层…...
Kali 更换源(超详细,附国内优质镜像源地址)
1.进入管理员下的控制台。 2. 输入密码后点击“授权”。 3.在控制台内输入下面的内容。 vim /etc/apt/sources.list 4.敲击回车后会进入下面的页面。 5.来到这个页面后的第一部是按键盘上的“i”键,左下角出现“插入”后说明操作正确。 6.使用“#”将原本的源给注释…...
Java版工程项目管理系统平台+java版企业工程系统源码+助力工程企业实现数字化管理
Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下: 首页 工作台:待办工作、消息通知、预警信息,点击可进入相应的列表 项目进度图表:选择(总体或单个)项目显示1…...
搜索引擎测试报告
文章目录 一、项目背景二、项目功能三、测试目的四、测试环境五、测试计划1、功能测试2、自动化测试 六、测试结果 一、项目背景 java官方文档是我们在学习java语言中不可或缺的权威资料。相比于各种网站的Java资料,官方文档无论是语言表达还是组织方式都要更加全面…...
4年的测试工程师,你遇到过自身瓶颈期吗?又是怎样度过的?
从毕业到现在已经快4年啦,一直软件测试行业混迹。我不是牛人,但是自我感觉还算是个合格的测试工程师,有必要写下自己将近4年来的经历,给自我以提示,给刚入行的朋友提供点参考。 貌似这一点适应的行业最广,…...
【Python零基础学习入门篇④】——第四节:Python的列表、元组、集合和字典
⬇️⬇️⬇️⬇️⬇️⬇️ ⭐⭐⭐Hello,大家好呀我是陈童学哦,一个普通大一在校生,请大家多多关照呀嘿嘿😁😊😘 🌟🌟🌟技术这条路固然很艰辛,但既已选择&…...
3.6 cache存储器
学习步骤: 我会采取以下几个步骤来学习Cache存储器: 确定学习目标:Cache存储器作为一种高速缓存存储器,通常用于提高计算机系统的运行效率。因此,我需要明确学习Cache存储器的目的,包括了解其原理、结构和…...
Ubuntu零基础安装
Ubuntu零基础安装 首先我们需要安装VM,再安装ubuntu。 1、安装VM 进入VM官网 VM官网地址 选择下载试用版 下载Windows版本 下载完成后,点击安装包进行安装 至此就安装完毕了。 桌面会出现VM的图标。 点击打开,弹出如下画面: …...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...



