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 好处: 无侵入式的给方法增强功能 2.2 动态代理三要素: 1,真正干活的对象 2,代理对象 3,利用代理调用方法 切记一点:代理可以增强或者拦截的方法都在接口中,接口需要写在…...
github Release 下载加速,绿色合法,遥遥领先
你有没有这样一个困惑,当你寻找了很久终于找到一个解决问题的方案,发现这个工具在 GitHub 上,接下来等待我们的就是遥遥无期的龟速下载。 文章目录 前言下载测试加速下载操作 视频讲解 遥遥领先 前言 GitHub 作为程序员的知识宝库ÿ…...
RabbitMQ消息中间件概述
1.什么是RabbitMQ RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现。AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有很多公开标准(如 COBAR的 IIOP ,或者是 SOAP 等&…...
12V手电钻保护板如何接线演示
爱做手工的小伙伴们肯定会用到手电钻,那么电池消耗完了,或要换的,或要自己动手做几个备用电源,关键点就是电路保护板的接线。废话不多说,直接上板子看实操。 文章目录 一、线路板图1、输入接线2、输出接线 二、接线方法…...
基于SpringBoot的教学辅助平台
目录 前言 一、技术栈 二、系统功能介绍 学生信息管理 教师信息管理 课程信息管理 科目分类管理 班级分类管理 课程作业管理 交流论坛管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用,管理…...
Qt 读写数据流文件(转 CppGuiProgrammingWithQt4)
读取文件: update 20140525:添加线程处理,在读取大文件时优化,防止 app 出现 application 假死状态。 bool SpreadSheet::readFile(const QString &filePath){QFile file(filePath);if ( !file.open(QIODevice::ReadOnly)) …...
Pygame中将鼠标形状设置为图片2-2
3 编写主程序 在主程序中,首先创建屏幕并且完成一些准备工作,之后在while循环中不断更新sprite实例即可。 3.1 创建屏幕及准备工作 创建屏幕及准备工作的代码如图5所示。 图5 创建屏幕及准备工作 其中,第20行代码调用pygame.mouse模块中的…...
GPU 基础知识整理
萌新: 在接触一款硬件时我会:基础硬件结构,线程结构,内存布局,数据吞吐量,等方面进行学习 首先GPU的特点: 并行性能:GPU 是专门设计用于并行计算的硬件,通常具有大量的处理单元&am…...
stable diffusion API接口 + 扩展接口
文章目录 概要流程页面接口调用展示txt2img接口AutoDL设置扩展接口 概要 调研Stable Diffusion二次开发,查看接口文档。 基于AutoDL算力服务器,直接安装部署,非常容易上手,部署教程放下面了。 部署教程 流程 页面接口调用 页面…...
MySQL数据库基本操作和完整性约束类型详解
目录 一、增删改查的sql语句二、表完整性约束1、表完整性约束的介绍2、常见的完整性约束类型3、表完整性约束实战操作3.1.主键primary key3.2.自增键auto_increment3.3.唯一键UNIQUE3.4.null与not null3.5.默认约束 一、增删改查的sql语句 SQL(Structured Query Lan…...
unity2022版本 实现加减进度条
简介 在现代游戏开发中,用户界面 (UI) 扮演着至关重要的角色,它不仅为玩家提供信息,还增强了游戏的可玩性。加减进度条是一种常见的UI元素,它可以用于显示游戏中的进度、倒计时、资源管理和其他关键信息。在这篇博客中࿰…...
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泛型
一.类型参数的约束 我们可以对泛型传进来的参数做一些约束,比如说 用extends表明传进来的参数类型必须是必须是某个类型的子类型或者本身 当然也可以用接口约束,也是用extends表明传进来的参数类型必须实现某个接口。用&连接,注意class…...
scss使用自定义函数实现单位像素随屏幕比例动态缩放
vue中通过变量和scss函数来动态实现动态缩放像素 简单来说就是比例缩小时,像素单位变大,从而字体大小相对不变,以下仅处理比例缩小的状况 自定义一个属性–size,初始值为1px template <template><div class"hom…...
Django 静态自定义化配置
STATIC # APP本地静态资源目录(就APP对应的) STATIC_URL "/static/"# 远程静态文件URL(少用) REMOTE_STATIC_URL# 外部引用静态文件目录(外层的) 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:安装 composer require hyperf/websocket-server2:配置 Server 修改 config/autoload/server.php,增加以下配置。 return [servers > [[name > ws,type > Server::SERVER_WEBSOCKET,host > 0.0.0.0,port > 9502,sock_typ…...
前端模块化
当我们从公司招聘上看到要求模块化的内容。 能从这几个角度回答,就说明我们是懂模块化的。 1. 模块化的本意,是当遇到一个复杂项目的时候(简单的不建议用),把这个复杂的问题拆分成相对独立的模块,降低程序…...
如何使用Docker轻松构建和管理应用程序(一)
如今Docker的使用已经非常普遍,特别在一线互联网公司。使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力。在云服务概念兴起之后,Docker的使用场景和范围进一步发展,如今在微服务架构越来越流行的情况下&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(当前位置的经度: res.longitude);console.log(当前位…...
鸿蒙页面代码构建:基于 HarmonyOS 6.0 的跨端开发实战
鸿蒙页面代码构建:基于 HarmonyOS 6.0 的跨端开发实战 前言 随着移动互联网和物联网的深度融合,应用开发正在从单一平台走向跨端、多终端协作的时代。华为鸿蒙操作系统(HarmonyOS)自诞生以来,一直致力于为开发者提供统…...
3步掌握Beyond Compare 5密钥生成:从原理到实践完整指南
3步掌握Beyond Compare 5密钥生成:从原理到实践完整指南 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen Beyond Compare作为一款功能强大的文件对比工具,其授权验证机制基…...
AssetStudio实战指南:解锁Unity游戏资源的完整解决方案
AssetStudio实战指南:解锁Unity游戏资源的完整解决方案 【免费下载链接】AssetStudio AssetStudio - Based on the archived Perfares AssetStudio, I continue Perfares work to keep AssetStudio up-to-date, with support for new Unity versions and additional…...
C语言实现热水器温度控制PID算法详解与嵌入式实战
1. 项目概述与核心价值最近在整理一些嵌入式开发的老项目,翻出来一个用C语言写的热水器温度控制PID算法示例。这玩意儿虽然代码量不大,但麻雀虽小五脏俱全,把PID控制的核心思想、参数整定、抗积分饱和这些关键点都体现出来了。对于刚接触自动…...
Arm Neoverse CMN-650架构解析与配置优化指南
1. Arm Neoverse CMN-650架构概览在现代多核处理器系统中,一致性互连网络是实现高效数据共享的关键基础设施。作为Arm Neoverse平台的核心组件,CMN-650采用创新的Mesh架构设计,为多核SoC提供了高带宽、低延迟的片上互连解决方案。与传统的总线…...
使用Taotoken的Token Plan套餐实现更具成本优势的持续调用
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 使用Taotoken的Token Plan套餐实现更具成本优势的持续调用 对于有稳定大模型调用需求的开发者或团队而言,成本的可预测…...
NExT-GPT:端到端任意模态大模型架构解析与实战指南
1. 项目概述:当多模态大模型遇见“全感官”交互最近在和朋友聊起多模态大模型时,大家总绕不开一个话题:现有的模型,无论是GPT-4V还是Gemini,虽然能“看”能“说”,但总感觉少了点什么。它们更像是一个单向的…...
保姆级教程:从NCBI下载序列到MEGA7构建进化树(附拟南芥SPL15基因实战)
生物信息学实战:从基因检索到进化树构建的全流程解析 在分子生物学研究中,系统进化分析是理解基因家族演化关系的重要工具。对于刚接触生物信息学的学生来说,从零开始完成一个完整的进化树分析项目往往面临诸多挑战——如何获取目标基因序列…...
STM32的RTC掉电还能走时?深入聊聊后备域和纽扣电池那点事
STM32的RTC掉电还能走时?深入聊聊后备域和纽扣电池那点事 当你在深夜调试STM32的RTC功能时,是否曾好奇过这个小巧的实时时钟为何能在主电源断开后依然精准走时?这背后隐藏着STM32芯片设计中一个精妙的电源管理机制——后备域(Back…...
iOS越狱技术深度解析:安全漏洞利用与系统权限获取方案
iOS越狱技术深度解析:安全漏洞利用与系统权限获取方案 【免费下载链接】Jailbreak iOS 26.4 - 26, 17 - 17.7.5 & iOS 18 - 18.7.3 Jailbreak Tools, Cydia/Sileo/Zebra Tweaks & Jailbreak News Updates || AI Jailbreak Finder 👇 项目地址:…...
