浅谈动态代理

news2024/10/1 7:34:03

什么是动态代理?


以下为个人理解:

  • 动态代理就是在程序运行的期间,动态地针对对象的方法进行增强操作。并且这个动作的执行者已经不是"this"对象了,而是我们创建的代理对象,这个代理对象就是类似中间人的角色,帮助我们为目标方法嵌入一些其他的逻辑进去。

jdk动态代理的原理


  • jdk自带的动态代理的工作原理是利用反射的newInstance,创建一个代理对象(proxy),获取到目标接口的方法,然后我们就可以在Invoke之前或之后做操作。它抽取出了一个invokeHandler,里面就有目标method。

  • 试想一下,当我们拥有了class对象,增强逻辑(invokeHandler),也就是增强的目标方法之后,我们自己利用反射(不利用Proxy)也可以很容易写出我们自己的动态代理。但是问题就在于,我们只有明确了目标类之后,通过自己编写Proxy类,实现目标接口,往里面塞invoktionHandler, 最后New出来这个实实在在的对象。而jdk提供的动态代理,却可以在并不知情的情况下,帮我们做这一系列的动作。

  • jdk生成代理类时,并没有经历源码阶段,编译阶段,而是直接到字节码阶段,它生成的代理类是看不到的,因为它直接就是字节码文件了。 它帮我们继承了Proxy类,并且还动态的帮助我们继承了目标接口。也就是说,它帮我们写代码了。里面用到的技术,是ASM技术,它可以直接生成我们想要的字节码。

  • jdk方法反射调用优化:

  • invoke() 利用反射进行本地调用,效率低下,它在调用了一定的次数(16)之后会生成实例化对象,变成正常调用。

InvocationHandler接口

publicinterfaceInvocationHandler {

publicObjectinvoke(Objectproxy, Methodmethod, Object[] args)throwsThrowable;

}

源码

@CallerSensitive

publicstaticObjectnewProxyInstance(ClassLoaderloader,

Class<?>[] interfaces,

InvocationHandlerh)

throwsIllegalArgumentException

{

Objects.requireNonNull(h);

finalClass<?>[] intfs=interfaces.clone();

finalSecurityManagersm=System.getSecurityManager();

if (sm!=null) {

checkProxyAccess(Reflection.getCallerClass(), loader, intfs);

}

/*

* Look up or generate the designated proxy class.

*/

Class<?>cl=getProxyClass0(loader, intfs);

/*

* Invoke its constructor with the designated invocation handler.

*/

try {

if (sm!=null) {

checkNewProxyPermission(Reflection.getCallerClass(), cl);

}

finalConstructor<?>cons=cl.getConstructor(constructorParams);

finalInvocationHandlerih=h;

if (!Modifier.isPublic(cl.getModifiers())) {

AccessController.doPrivileged(newPrivilegedAction<Void>() {

publicVoidrun() {

cons.setAccessible(true);

returnnull;

}

});

}

returncons.newInstance(newObject[]{h});

} catch (IllegalAccessException|InstantiationExceptione) {

thrownewInternalError(e.toString(), e);

} catch (InvocationTargetExceptione) {

Throwablet=e.getCause();

if (tinstanceofRuntimeException) {

throw (RuntimeException) t;

} else {

thrownewInternalError(t.toString(), t);

}

} catch (NoSuchMethodExceptione) {

thrownewInternalError(e.toString(), e);

}

}

cglib动态代理的原理


  • cglib动态代理的原理跟jdk的类似,只不过它是基于父类继承,也就是不需要实现接口就可以做增强。它的内部并不是InvoktionHandler,而是方法拦截器 MethodInterceptor 。

  • 前面的jdk动态代理,它是利用ASM技术帮我们动态编写了一个proxy对象,其中继承了Proxy父类,实现了目标接口,而cglib则是利用ASM直接帮助我们继承了目标类,不需要接口。

  • 并且有所区别的是,它不仅仅通过反射拿到method,还拿到了MethodProxy。

  • MethodInterceptor接口 继承了Callback接口,它的拦截方法里面有一个特殊的参数 MethodProxy,这玩意可以不通过反射调用方法,通过invokeSuper() 方法可以直接正常调用。

  • MethodProxy是怎么做到正常调用的?

  • 其实就是我们前面提到的,继承了Proxy父类之后,就得到了父类的原始方法,当我调用invokeSuper的时候,直接调用的就是父类的原始方法。

MethodInterceptor

publicinterfaceMethodInterceptorextendsCallback {

Objectintercept(Objectvar1, Methodvar2, Object[] var3, MethodProxyvar4) throwsThrowable;

}

MethodProxy

  • invoke() 无反射调用

  • invokeSuper() 无反射调用

publicObjectinvoke(Objectobj, Object[] args) throwsThrowable {

try {

this.init();

MethodProxy.FastClassInfofci=this.fastClassInfo;

returnfci.f1.invoke(fci.i1, obj, args);

} catch (InvocationTargetExceptionvar4) {

throwvar4.getTargetException();

} catch (IllegalArgumentExceptionvar5) {

if (this.fastClassInfo.i1<0) {

thrownewIllegalArgumentException("Protected method: "+this.sig1);

} else {

throwvar5;

}

}

}

publicObjectinvokeSuper(Objectobj, Object[] args) throwsThrowable {

try {

this.init();

MethodProxy.FastClassInfofci=this.fastClassInfo;

returnfci.f2.invoke(fci.i2, obj, args);

} catch (InvocationTargetExceptionvar4) {

throwvar4.getTargetException();

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/338319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文】基于AI边缘计算的铁路行车视频监控智能识别研究

本文转载自《科技与创新》2022年第01期 作者&#xff1a;李博&#xff0c; 杨欣 单位&#xff1a;中国铁路武汉局集团有限公司麻城车务段 摘要 随着铁路信息化建设的不断推进&#xff0c;视频监控设备应用到越来越多岗位中&#xff0c;运用智能化手段管理工作人员必将成为一…

BiseNet v1论文及其代码详解

来源&#xff1a;投稿 作者&#xff1a;蓬蓬奇 编辑&#xff1a;学姐 BiSeNet v1说明&#xff1a; 文章链接&#xff1a;https://arxiv.org/abs/1808.00897 官方开源代码&#xff1a;https://github.com/CoinCheung/BiSeNet &#xff08;本文未使用&#xff09; 文章标题&am…

宝塔搭建实战php开源likeadmin通用管理admin端vue3源码(二)

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 上一期给大家分享了server端的部署方式&#xff0c;今天来给大家分享admin端在本地搭建&#xff0c;与打包发布到宝塔的方法。感兴趣的朋友可以自行下载学习。 技术架构 vscode node16 vue3 elementPlus vit…

1627_MIT 6.828 PC硬件与x86编程幻灯片资料阅读

全部学习汇总&#xff1a; GreyZhang/g_unix: some basic learning about unix operating system. (github.com) 按照MIT 6.828的计划表继续往下走&#xff0c;看到了一份需要看的阅读资料&#xff0c;也就是这次整理的这一份幻灯片。其实&#xff0c;为了解决之前的疑惑相关的…

4.5.7 HashMap

文章目录1.概述2.练习&#xff1a;字符串中字符统计3.Map与HashMap的比较4.HashMap扩容1.概述 HashMap底层是一个Entry[ ]数组,长度为16&#xff0c;当存放数据时,会根据hash算法来计算数据的存放位置 算法:hash(key)%n , n就是数组的长度,其实也就是集合的容量 当计算的位置没…

计算机网络-无线网络

文章目录前言无线局域网 WLAN无线局域网的组成移动自组网络无线传感器网络 WSN (Wireless Sensor Network)802.11 局域网的物理层802.11 局域网的 MAC 层协议WLAN无线控制器和FIT&#xff08;瘦&#xff09; AP总结前言 本博客仅做学习笔记&#xff0c;如有侵权&#xff0c;联…

Python-项目实战--飞机大战-敌机出场(6)

目标使用定时器添加敌机设计Enemy类1.使用定时器添加敌机敌机出现出现的规律&#xff1a;游戏启动后&#xff0c;每隔1秒会出现一架敌机每架敌机向屏幕下方飞行&#xff0c;飞行速度各不相同每架敌机出现的水平位置也不尽相同当敌机从屏幕下方飞出&#xff0c;不会再飞回到屏幕…

常见的历史漏洞之 weblogic+ Thinkphp5

数据来源 本文仅用于信息安全的学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若观众因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与本人无关。 01 Weblogic相关介绍 》Weblogic介绍 》Weblogic特征 》历史漏洞 02 Weblogic漏洞利…

代码覆盖率工具OpenCppCoverage在Windows上的使用

OpenCppCoverage是用在Windows C上的开源的代码覆盖率工具&#xff0c;源码地址为https://github.com/OpenCppCoverage/OpenCppCoverage &#xff0c;最新发布版本为0.9.9.0&#xff0c;License为GPL-3.0。 从https://github.com/OpenCppCoverage/OpenCppCoverage/releases 下载…

python制作贪吃蛇小游戏,畅玩无限制

前言 大家早好、午好、晚好吖 ❤ ~ 现在这年头&#xff0c;无论玩个什么游戏都有健康机制&#xff0c; 这让我们愉悦玩游戏得步伐变得承重起来&#xff0c; 于是无聊之下我写了个贪吃蛇小游戏&#xff0c;来玩个快乐 代码展示 导入模块 import random import sys import …

关于一笔画问题的一些思考(欧拉路Fleury算法、逐步插入回路法、以及另一种可能的解法)

前言这是一个经典的图论问题了最近复习离散的时候又恰好看到了&#xff0c;发现自己以前的解法似乎有点bug然后开始出反例卡自己&#xff0c;结果发现卡不掉&#xff1f;然后再好好想了想&#xff0c;发现这个看起来有问题的做法可能确实没问题。注意&#xff1a;欧拉路、欧拉回…

透射式光电对管测量脉搏硬件电路设计

目录 前言 一、脉搏测量方法 二、脉搏测量原理 2.1 脉搏信号处理整体电路 2.2 信号采集电路 2.3 信号放大电路 2.4 波形整形电路 总结 前言 脉搏测量仪的设计是通过检测心跳的血液变化&#xff0c;产生不同的反射信号&#xff0c;用传感器将脉搏的跳动转换为电信号&…

Servlet实现表白墙

目录 一、表白墙简介 二、代码实现 1、约定前后端交互的接口 2、后端代码实现 3、前端代码实现 三、效果演示 一、表白墙简介 在表白墙页面中包含三个文本框&#xff0c;分别表示表白者&#xff0c;表白对象&#xff0c;表白内容&#xff0c;在文本框中输入内容之后&…

基于Web Speech API给ChatGPT加上语音功能,距离MOSS又近了一步

目录 前言 起步 实现过程 webkitSpeechRecognition speechSynthesis 小例子 遇到的问题 效果展示 总结 前言 去年写了两篇关于接入ChatGPT的文章&#xff1a;微信接入ChatGPT&#xff0c;使用NodeChatGPTWechaty做一个微信机器人_DieHunter1024的博客-CSDN博客 站在巨…

ChatGPT接入个人微信企业微信(国内通用)

ChatGPT近期以强大的对话和信息整合能力风靡全网&#xff0c;可以写代码、改论文、讲故事&#xff0c;几乎无所不能&#xff0c;这让人不禁有个大胆的想法&#xff0c;能否用他的对话模型把我们的微信打造成一个智能机器人&#xff0c;可以在与好友对话中给出意想不到的回应&am…

controller-runtime源码学习

本文基于controller-runtime v0.11.2版本进行源码学习 kubebuilder、operator-sdk这些框架都是在controller-runtime基础上做了一层封装&#xff0c;方便开发者快速生成项目的脚手架&#xff0c;本文会以kuebuilder搭建工程作为使用controller-runtime的demo进行源码分析 1、k…

paddle表情识别部署

表情识别模块1.环境部署1.1同样采用fastDeploy库1.2相关模型2.封装成静态库2.1参考[百度Paddle中PP-Mattingv2的部署并将之封装并调用一个C静态库](https://blog.csdn.net/weixin_43564060/article/details/128882099)2.2项目依赖添加2.3生成成功3.test3.1创建emotion_test项目…

多传感器融合定位十二-基于图优化的建图方法其一

多传感器融合定位十二-基于图优化的建图方法其一1. 基于预积分的融合方案流程1.1 优化问题分析1.2 预积分的作用1.3 基于预积分的建图方案流程2. 预积分模型设计3. 预积分在优化中的使用3.1 使用方法3.2 残差设计3.3 残差雅可比的推导3.3.1 姿态残差的雅可比3.3.2 速度残差的雅…

Python3.10新特性之match语句示例详解

这篇文章主要为大家介绍了Python3.10新特性之match语句示例详解&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步&#xff0c;早日升职加薪正文在Python 3.10发布之前&#xff0c;Python是没有类似于其他语言中switch语句的&…

Clip-path实现按钮流动边框动画

前言 &#x1f44f;Clip-path实现按钮流动边框动画&#xff0c;速速来Get吧~ &#x1f947;文末分享源代码。记得点赞关注收藏&#xff01; 1.实现效果 2.实现步骤 添加div标签 <div>苏苏_icon</div>添加样式 div {position: relative;width: 220px;height: 6…