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

Java之动态代理的详细解析

2. 动态代理

2.1 好处:

无侵入式的给方法增强功能

2.2 动态代理三要素:

1,真正干活的对象

2,代理对象

3,利用代理调用方法

切记一点:代理可以增强或者拦截的方法都在接口中,接口需要写在newProxyInstance的第二个参数里。

2.3 代码实现:

public class Test {public static void main(String[] args) {/*需求:外面的人想要大明星唱一首歌1. 获取代理的对象代理对象 = ProxyUtil.createProxy(大明星的对象);2. 再调用代理的唱歌方法代理对象.唱歌的方法("只因你太美");*///1. 获取代理的对象BigStar bigStar = new BigStar("鸡哥");Star proxy = ProxyUtil.createProxy(bigStar);
​//2. 调用唱歌的方法String result = proxy.sing("只因你太美");System.out.println(result);}
}
/*
*
* 类的作用:
*       创建一个代理
*
* */
public class ProxyUtil {/*** 方法的作用:*       给一个明星的对象,创建一个代理**  形参:*       被代理的明星对象**  返回值:*       给明星创建的代理**** 需求:*   外面的人想要大明星唱一首歌*   1. 获取代理的对象*      代理对象 = ProxyUtil.createProxy(大明星的对象);*   2. 再调用代理的唱歌方法*      代理对象.唱歌的方法("只因你太美");* */public static Star createProxy(BigStar bigStar){/* java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:
​public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)参数一:用于指定用哪个类加载器,去加载生成的代理类参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法参数三:用来指定生成的代理对象要干什么事情*/Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),//参数一:用于指定用哪个类加载器,去加载生成的代理类new Class[]{Star.class},//参数二:指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法//参数三:用来指定生成的代理对象要干什么事情new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {/** 参数一:代理的对象* 参数二:要运行的方法 sing* 参数三:调用sing方法时,传递的实参* */if("sing".equals(method.getName())){System.out.println("准备话筒,收钱");}else if("dance".equals(method.getName())){System.out.println("准备场地,收钱");}//去找大明星开始唱歌或者跳舞//代码的表现形式:调用大明星里面唱歌或者跳舞的方法return method.invoke(bigStar,args);}});return star;}
}
public interface Star {//我们可以把所有想要被代理的方法定义在接口当中//唱歌public abstract String sing(String name);//跳舞public abstract void dance();
}
public class BigStar implements Star {private String name;
​
​public BigStar() {}
​public BigStar(String name) {this.name = name;}
​//唱歌@Overridepublic String sing(String name){System.out.println(this.name + "正在唱" + name);return "谢谢";}
​//跳舞@Overridepublic void dance(){System.out.println(this.name + "正在跳舞");}
​/*** 获取* @return name*/public String getName() {return name;}
​/*** 设置* @param name*/public void setName(String name) {this.name = name;}
​public String toString() {return "BigStar{name = " + name + "}";}
}
​

2.4 额外扩展

动态代理,还可以拦截方法

比如:

在这个故事中,经济人作为代理,如果别人让邀请大明星去唱歌,打篮球,经纪人就增强功能。

但是如果别人让大明星去扫厕所,经纪人就要拦截,不会去调用大明星的方法。

/*
* 类的作用:
*       创建一个代理
* */
public class ProxyUtil {public static Star createProxy(BigStar bigStar){public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),new Class[]{Star.class},new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if("cleanWC".equals(method.getName())){System.out.println("拦截,不调用大明星的方法");return null;}//如果是其他方法,正常执行return method.invoke(bigStar,args);}});return star;}
}

2.5 动态代理的练习

对add方法进行增强,对remove方法进行拦截,对其他方法不拦截也不增强

public class MyProxyDemo1 {public static void main(String[] args) {//动态代码可以增强也可以拦截//1.创建真正干活的人ArrayList<String> list = new ArrayList<>();
​//2.创建代理对象//参数一:类加载器。当前类名.class.getClassLoader()//                 找到是谁,把当前的类,加载到内存中了,我再麻烦他帮我干一件事情,把后面的代理类,也加载到内存
​//参数二:是一个数组,在数组里面写接口的字节码文件对象。//                  如果写了List,那么表示代理,可以代理List接口里面所有的方法,对这些方法可以增强或者拦截//                  但是,一定要写ArrayList真实实现的接口//                  假设在第二个参数中,写了MyInter接口,那么是错误的。//                  因为ArrayList并没有实现这个接口,那么就无法对这个接口里面的方法,进行增强或拦截//参数三:用来创建代理对象的匿名内部类List proxyList = (List) Proxy.newProxyInstance(//参数一:类加载器MyProxyDemo1.class.getClassLoader(),//参数二:是一个数组,表示代理对象能代理的方法范围new Class[]{List.class},//参数三:本质就是代理对象new InvocationHandler() {@Override//invoke方法参数的意义//参数一:表示代理对象,一般不用(了解)//参数二:就是方法名,我们可以对方法名进行判断,是增强还是拦截//参数三:就是下面第三步调用方法时,传递的参数。//举例1://list.add("阿玮好帅");//此时参数二就是add这个方法名//此时参数三 args[0] 就是 阿玮好帅//举例2://list.set(1, "aaa");//此时参数二就是set这个方法名//此时参数三  args[0] 就是 1  args[1]"aaa"public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//对add方法做一个增强,统计耗时时间if (method.getName().equals("add")) {long start = System.currentTimeMillis();//调用集合的方法,真正的添加数据method.invoke(list, args);long end = System.currentTimeMillis();System.out.println("耗时时间:" + (end - start));//需要进行返回,返回值要跟真正增强或者拦截的方法保持一致return true;}else if(method.getName().equals("remove") && args[0] instanceof Integer){System.out.println("拦截了按照索引删除的方法");return null;}else if(method.getName().equals("remove")){System.out.println("拦截了按照对象删除的方法");return false;}else{//如果当前调用的是其他方法,我们既不增强,也不拦截method.invoke(list,args);return null;}}});
​//3.调用方法//如果调用者是list,就好比绕过了第二步的代码,直接添加元素//如果调用者是代理对象,此时代理才能帮我们增强或者拦截
​//每次调用方法的时候,都不会直接操作集合//而是先调用代理里面的invoke,在invoke方法中进行判断,可以增强或者拦截proxyList.add("aaa");proxyList.add("bbb");proxyList.add("ccc");proxyList.add("ddd");
​proxyList.remove(0);proxyList.remove("aaa");
​
​//打印集合System.out.println(list);}
}

相关文章:

Java之动态代理的详细解析

2. 动态代理 2.1 好处&#xff1a; 无侵入式的给方法增强功能 2.2 动态代理三要素&#xff1a; 1&#xff0c;真正干活的对象 2&#xff0c;代理对象 3&#xff0c;利用代理调用方法 切记一点&#xff1a;代理可以增强或者拦截的方法都在接口中&#xff0c;接口需要写在…...

github Release 下载加速,绿色合法,遥遥领先

你有没有这样一个困惑&#xff0c;当你寻找了很久终于找到一个解决问题的方案&#xff0c;发现这个工具在 GitHub 上&#xff0c;接下来等待我们的就是遥遥无期的龟速下载。 文章目录 前言下载测试加速下载操作 视频讲解 遥遥领先 前言 GitHub 作为程序员的知识宝库&#xff…...

RabbitMQ消息中间件概述

1.什么是RabbitMQ RabbitMQ是一个由erlang开发的AMQP&#xff08;Advanced Message Queue &#xff09;的开源实现。AMQP 的出现其实也是应了广大人民群众的需求&#xff0c;虽然在同步消息通讯的世界里有很多公开标准&#xff08;如 COBAR的 IIOP &#xff0c;或者是 SOAP 等&…...

12V手电钻保护板如何接线演示

爱做手工的小伙伴们肯定会用到手电钻&#xff0c;那么电池消耗完了&#xff0c;或要换的&#xff0c;或要自己动手做几个备用电源&#xff0c;关键点就是电路保护板的接线。废话不多说&#xff0c;直接上板子看实操。 文章目录 一、线路板图1、输入接线2、输出接线 二、接线方法…...

基于SpringBoot的教学辅助平台

目录 前言 一、技术栈 二、系统功能介绍 学生信息管理 教师信息管理 课程信息管理 科目分类管理 班级分类管理 课程作业管理 交流论坛管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理…...

Qt 读写数据流文件(转 CppGuiProgrammingWithQt4)

读取文件&#xff1a; update 20140525&#xff1a;添加线程处理&#xff0c;在读取大文件时优化&#xff0c;防止 app 出现 application 假死状态。 bool SpreadSheet::readFile(const QString &filePath){QFile file(filePath);if ( !file.open(QIODevice::ReadOnly)) …...

Pygame中将鼠标形状设置为图片2-2

3 编写主程序 在主程序中&#xff0c;首先创建屏幕并且完成一些准备工作&#xff0c;之后在while循环中不断更新sprite实例即可。 3.1 创建屏幕及准备工作 创建屏幕及准备工作的代码如图5所示。 图5 创建屏幕及准备工作 其中&#xff0c;第20行代码调用pygame.mouse模块中的…...

GPU 基础知识整理

萌新&#xff1a; 在接触一款硬件时我会&#xff1a;基础硬件结构&#xff0c;线程结构&#xff0c;内存布局&#xff0c;数据吞吐量&#xff0c;等方面进行学习 首先GPU的特点: 并行性能&#xff1a;GPU 是专门设计用于并行计算的硬件&#xff0c;通常具有大量的处理单元&am…...

stable diffusion API接口 + 扩展接口

文章目录 概要流程页面接口调用展示txt2img接口AutoDL设置扩展接口 概要 调研Stable Diffusion二次开发&#xff0c;查看接口文档。 基于AutoDL算力服务器&#xff0c;直接安装部署&#xff0c;非常容易上手&#xff0c;部署教程放下面了。 部署教程 流程 页面接口调用 页面…...

MySQL数据库基本操作和完整性约束类型详解

目录 一、增删改查的sql语句二、表完整性约束1、表完整性约束的介绍2、常见的完整性约束类型3、表完整性约束实战操作3.1.主键primary key3.2.自增键auto_increment3.3.唯一键UNIQUE3.4.null与not null3.5.默认约束 一、增删改查的sql语句 SQL&#xff08;Structured Query Lan…...

unity2022版本 实现加减进度条

简介 在现代游戏开发中&#xff0c;用户界面 (UI) 扮演着至关重要的角色&#xff0c;它不仅为玩家提供信息&#xff0c;还增强了游戏的可玩性。加减进度条是一种常见的UI元素&#xff0c;它可以用于显示游戏中的进度、倒计时、资源管理和其他关键信息。在这篇博客中&#xff0…...

COCO数据集中图像的caption读取到txt文件

annotations_trainval2017.zip import os import shutil import jsoncaptions_path r"G:\SketchDiffusion\Sketchycoco\Dataset\annotations\captions_train2017.json" # 读取json文件 with open(captions_path, r) as f1:dictortary json.load(f1)# 得到images和…...

再谈Java泛型

一.类型参数的约束 我们可以对泛型传进来的参数做一些约束&#xff0c;比如说 用extends表明传进来的参数类型必须是必须是某个类型的子类型或者本身 当然也可以用接口约束&#xff0c;也是用extends表明传进来的参数类型必须实现某个接口。用&连接&#xff0c;注意class…...

scss使用自定义函数实现单位像素随屏幕比例动态缩放

vue中通过变量和scss函数来动态实现动态缩放像素 简单来说就是比例缩小时&#xff0c;像素单位变大&#xff0c;从而字体大小相对不变&#xff0c;以下仅处理比例缩小的状况 自定义一个属性–size&#xff0c;初始值为1px template <template><div class"hom…...

Django 静态自定义化配置

STATIC # APP本地静态资源目录&#xff08;就APP对应的&#xff09; STATIC_URL "/static/"# 远程静态文件URL&#xff08;少用&#xff09; REMOTE_STATIC_URL# 外部引用静态文件目录&#xff08;外层的&#xff09; STATICFILES_DIRS [os.path.join(BASE_DIR, &…...

TensorFlow入门(十四、数据读取机制(1))

TensorFlow的数据读取方式 TensorFlow的数据读取方式共有三种,分别是: ①预加载数据(Preloaded data) 预加载数据的方式,其实就是静态图(Graph)的模式。即将数据直接内嵌到Graph中,再把Graph传入Session中运行。 示例代码如下: import tensorflow.compat.v1 as tf tf.disabl…...

hyperf框架WebSocket 服务

1&#xff1a;安装 composer require hyperf/websocket-server2&#xff1a;配置 Server 修改 config/autoload/server.php&#xff0c;增加以下配置。 return [servers > [[name > ws,type > Server::SERVER_WEBSOCKET,host > 0.0.0.0,port > 9502,sock_typ…...

前端模块化

当我们从公司招聘上看到要求模块化的内容。 能从这几个角度回答&#xff0c;就说明我们是懂模块化的。 1. 模块化的本意&#xff0c;是当遇到一个复杂项目的时候&#xff08;简单的不建议用&#xff09;&#xff0c;把这个复杂的问题拆分成相对独立的模块&#xff0c;降低程序…...

如何使用Docker轻松构建和管理应用程序(一)

如今Docker的使用已经非常普遍&#xff0c;特别在一线互联网公司。使用Docker技术可以帮助企业快速水平扩展服务&#xff0c;从而到达弹性部署业务的能力。在云服务概念兴起之后&#xff0c;Docker的使用场景和范围进一步发展&#xff0c;如今在微服务架构越来越流行的情况下&a…...

uniapp 获取地理位置(uni#getLocation和高德sdk获取中文地址)

参考 https://uniapp.dcloud.net.cn/api/location/location.html https://ask.dcloud.net.cn/article/35070 1. uniapp api获取经纬度 uni.getLocation({type: wgs84,success: function (res) {console.log(当前位置的经度&#xff1a; res.longitude);console.log(当前位…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...

跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践

在电商行业蓬勃发展的当下&#xff0c;多平台运营已成为众多商家的必然选择。然而&#xff0c;不同电商平台在商品数据接口方面存在差异&#xff0c;导致商家在跨平台运营时面临诸多挑战&#xff0c;如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...

【工具教程】多个条形码识别用条码内容对图片重命名,批量PDF条形码识别后用条码内容批量改名,使用教程及注意事项

一、条形码识别改名使用教程 打开软件并选择处理模式&#xff1a;打开软件后&#xff0c;根据要处理的文件类型&#xff0c;选择 “图片识别模式” 或 “PDF 识别模式”。如果是处理包含条形码的 PDF 文件&#xff0c;就选择 “PDF 识别模式”&#xff1b;若是处理图片文件&…...

零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)

经过前面几期的内容我们学习了很多网络安全的知识&#xff0c;而这期内容就涉及到了前面的第六期-RCE模块&#xff0c;第七期-File inclusion模块&#xff0c;第八期-Unsafe Filedownload模块。 什么是"遍历"呢&#xff1a;对学过一些开发语言的朋友来说应该知道&…...