从兄弟到父子:动态代理在民间是怎么玩的?

Cglib动态代理需要用到的jar包 Cglib动态代理需要用到的jar包 http://www.cnblogs.com/mfrank/p/8150925.html 立即下载

前言:本文为《Java帝国之动态代理》的姊妹篇, 讲述动态代理的另外一种实现即CGLib的设计过程。

当IO大臣绞尽脑汁地在府中设计Java动态代理的时候,他并不知道,在帝国的一个小小的部落,一个年轻的小伙子正在为同样的问题而苦恼。

师傅刚刚给小伙子下达了任务:在运行时对一个类进行扩展, 例如有个类叫HelloWorld,要在运行时给他加点日志输出的代码。

0?wx_fmt=png

师傅特别告诉年轻人:“大胖, 你要注意,是在运行时,而不是在编译时! 不能改变原来的代码!”

年轻气盛的张大胖还不太清楚为什么要这么干,不由地问道:“师傅,怎么会有这么稀奇古怪的要求啊?”

师傅说:“你先把这个东西给做出来,我以后自然会给你讲。”

张大胖研究了一段时间后得知,Java帝国严禁在运行时对一个类进行修改,比如HelloWorld 这个类,  一旦被装载进入JVM方法区,就不能改动了,那想在运行时给它的sayHello()方法中加点日志代码该怎么办呢?

大胖心想: 那其实只剩下一条路了,动态地生成一个新类, 让这个类作为代理HelloWorld去做事情。

0?wx_fmt=png

可是怎么才能动态地生成一个类呢? 张大胖心想: 我曾经看过帝国的《JVM规范》, 一个class文件那简直是太复杂了,难道让我去操作二进制代码去生成类?  那可要了我的小命了! 

张大胖拿着草稿图去找师傅:“师傅,我已经有了个初步想法, 可是不知道怎么去动态地生成类啊!”

师傅看了一眼说: “你这个类图有问题啊!”

“什么问题?”

“举个例子,有个函数如下

0?wx_fmt=png

现在你把HelloWorld变成了HelloWorldProxy, 而这个HelloWorldProxy又和原来的HelloWorld一毛钱关系都没有, 还能作为参数传递給hello方法吗? ”

张大胖挠挠头,挺不好意思 : “奥,那是肯定不行喽,没法利用多态,这样,我可以让这个动态生成的HelloWorldProxy继承自HelloWorld, 师傅你看看这样行不行:”

0?wx_fmt=png

“这样好多了, 但是还有一个问题,就是代码的复用性不够。”

“什么复用性?”

“你想想啊,现在你只有一个类就是HelloWorld , 如果还有很多别的类例如Person, Student, Employee,Teacher ..... 他们相应的方法都要加上日志输出,按照你的办法,就得有无数这样的代码了:

Logger.startLog();

super.XXXX();

Logger.endLog();”

“奥,我明白了,就是要想办法复用这一段代码,那我可以再增加一个中间层,就叫做LogInterceptor如何?”

0?wx_fmt=png

“孺子可教,你这个名称起得也不错,Interceptor,意味着拦截的意思。这样一来LogInterceptor就可以被其他类给复用了。”

“师傅, 回到我最初的问题, 怎么在运行时动态地生成Java Class啊? 总不能让我直接写Java字节码吧?”

“这个你不用担心,有个叫做ASM的家伙,他已经对底层的Java字节码操作做了封装,你直接调用它就行了”

(老刘提示: 请移步 《ASM: 一个低调成功者的自述》)

“好, 让我去看看,这个玩意儿到底怎么样。”

ASM确实挺难的, 虽然对字节码操作做了封装,但是非得理解JVM指令才行,张大胖不得不去学习一下JVM字节码的知识,两个月后,他终于能够使用ASM动态的在内存中创建类了。 

又花了两个月,张大胖终于把整个系统开发完成,现在的使用非常简单:

0?wx_fmt=png

张大胖把这个东西命名为动态代理, 因为所做的所有事情无非就是在运行时为原有的类建立一个代理,增加功能而已。 

过了两天, 师傅急匆匆地来找张大胖:“大胖, 我刚刚听说, Java帝国的IO大臣在JDK中加入了一个重要功能,叫做Java 动态代理,你赶紧研究下,看看和咱们做的有什么不同。”

大胖不敢怠慢,赶紧查看帝国发布的公告文书, 看完以后就放心了:“师傅, 这官方的动态代理有个重大的缺陷,就是必须有接口才能使用,而我们做的动态代理只要有个类就可以了, 我可以动态地生成一个子类。当然如果一个类被标记为final , 无法被继承,那就不行了。”

0?wx_fmt=png

“嗯,有点意思” 师傅说道 “这官方动态生成的HelloWorldProxy是HelloWorld的兄弟, 而我们动态生成的HelloWorldProxy是HelloWorld的孩子啊!”

“哈哈,果然是这样。 师傅,你还没给我说这玩意儿到底有啥用处呢”

“你没看官方的公告吗?”

“官方大话套话连篇,看不懂啊!”

“还拿之前的例子来说吧,你现在有很多类,例如Person, Student, Employee,Teacher ... , 每个类都有很多方法, 现在你想给这些方法加上日志输出,该怎么办呢?”

张大胖说:“我可以去改动代码, 嗯,这样改动量非常大,并且如果拿不到源码的话,就没办法了。”

“对啊,这时候动态代理不就派上用场了? 动态生成代理类PersonProxy, StudentProxy,EmployProxy... 等等, 让它们去继承Person, Student, Employee,   这样代理类就可以增加日志输出代码了。 你甚至可以把要添加日志功能的类和方法写到一个XML文件中去, 然后再写个工具去读取这个XML文件,自动地生成所有代理类,多方便啊。”

“奥,原来如此 ,不仅仅是日志,还有事务了, 权限检查了,都可以用这种办法,对吧 ” 张大胖一点就通。

“是这样的, 这就是AOP编程了。  对了,既然官方已经把动态代理这个名称给占了, 我们就得改名了,不能叫做动态代理了”

“师傅,这个我已经想好了,叫做Code Generation Library, 简称CGLib, 体现了技术的本质,就是一个代码生成的工具。”

后记:CGLIb为了提高性能,还用了一种叫做FastClass的方式来直接调用一个对象的方法,而不是通过反射。   由于涉及的代码太多,本文不再展示,一个具体的调用过程参见下图:

0?wx_fmt=png

最后,感谢“白色衬衫”同学在之前的留言中提出了“动态代理的兄弟、父子的关系”,给了我灵感写这篇文章。

(完)

你看到的只是冰山一角, 更多精彩文章,请移步《码农翻身2016文章精华》或者《码农翻身2017上半年文章精华》

有心得想和大家分享? 欢迎投稿 ! 我的联系方式:微信:liuxinlehan  QQ: 3340792577


640?

优秀人才不缺工作机会,只缺适合自己的好机会。但是他们往往没有精力从海量机会中找到最适合的那个。

100offer 会对平台上的人才和企业进行严格筛选,让「最好的人才」和「最好的公司」相遇。

扫描下方二维码,注册 100offer,谈谈你对下一份工作的期待。一周内,收到 5-10 个满足你要求的好机会!

0?wx_fmt=jpeg

cglib动态代理所需jar包 cglib2.2,asm3.3.jar 不导入asm.jar会出现Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.Type报错,参考文章: http://blog.youkuaiyun.com/xujingcheng123/article/details/79030216 立即下载

相关推荐

dxf-viewer 查看器

dxf-viewer SDK 的示例,它是一个基于 Three.js 和 Vue3 构建的基于 WebGL 的 BIM 模型查看器。它用于查看 DWG/DXF/PDF 文件。面积测量 - 角度测量 -标记。

qq_25547755的博客 866

CGLIB动态代理详解分析

CGLIB是强大的、高性能的代码生成库,被广泛应用于AOP框架,它底层使用ASM来操作字节码生成新的类,为对象引入间接级别,以控制对象的访问。CGLIB相比于JDK动态代理更加强大,JDK动态代理只能对接口进行代理,而CGLIB既可以代理普通类,也能够代理接口。

weixin_43397326的博客 6589

各种加法器的比对分析与Verilog实现(3)

了Kogge-Stone加法器和brent-kung加法器,本文将用Verilog代码进行实现。

Albert_yeager的博客 1199

cglib动态代理

CGLIB(Code Generation Library),是一个强大的,高性能,高质量的 Code 生成类库,它可以在运行期扩展 Java 类与实现 Java 接口。

NCS123456的博客 1万+

python自动交易 缠论_缠论自动交易系统实现了

一、缘起:缠中说禅的伟大,我想你只要上网搜索一下就知道了,他的才气不用我说,我只想说说他的《教你炒股票》系列文章,108篇文章,将他的股票操盘秘籍全部公开给广大的股友了,更有缠友将其理论写成公式,在网上也是广为流传,深受广大缠友们的喜爱。我也是缠中说禅的忠实崇拜者之一,从2008年开始每天都使用缠论来看盘,特别想将缠论写成交易系统,让计算加来帮助我们自动交易,从而减轻我们盯盘的辛劳,可是苦于没有好...

weixin_39970689的博客 4646

AD5700 HART芯片实战笔记:从时钟检测到数据收发,一个STM32工程师的踩坑实录

本文详细记录了STM32工程师在AD5700 HART芯片开发中的实战经验,涵盖时钟信号检测、RTS切换时序优化及HART数据解析等关键问题。通过硬件设计检查、定时器配置优化和大小端转换方案对比,解决了工业级芯片开发中的典型挑战,为嵌入式开发者提供宝贵参考。

weixin_42715608的博客 164

动态代理模式 -- Cglib代理

静态代理和 JDK 代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个 单独的对象,并没 有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是 Cglib 代理Cglib代理也叫作 子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将Cglib代理归属到动态代理。Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口.它广泛的被许多 AOP 的框架使用,例如 SpringAOP,实现方法拦截。

weixin_43739348的博客 1977

【创作赢红包】Gurobi学术版证书更新与Python环境配置全攻略

本文详细解析了Gurobi学术版证书过期后的完整更新流程与Python环境配置方法。从彻底清理旧版残留、手把手注册获取新许可证,到软件安装、证书激活,最后重点讲解如何将gurobipy接口正确配置到Python的site-packages目录,并提供了常见问题排查方案,帮助用户高效解决证书与配置难题。

efc1234567的博客 615

CGLIB 动态代理详解

CGLIB 是一个强大的代码生成库,它可以在运行时动态生成目标类的子类,从而实现对目标类的方法增强,也就是动态代理。与 JDK 动态代理不同,CGLIB 不需要目标类实现接口,它可以直接对类进行代理。这使得 CGLIB 在一些特定场景下具有很大的优势,比如对没有接口的类进行代理或者需要更灵活地控制代理行为时。

dawn191228的博客 2377

MemSeg:一种差异和共性来检测图像表面缺陷的半监督方法

本文认为人为创建类内差异和保持类内共性可以帮助模型实现更好的缺陷检测能力,从而更好地区分非正常图像。如图一所示。差异(differences):MemSeg引入人工模拟的异常图像在训练阶段使模型能够区分正常和异常的图像,减轻了半监督学习只能用正常样本进行训练的不足,然后在推理阶段可以直接输入图像无需做任何后处理。共性(commonalities):MemSeg引入了一个记忆池来记录正常样本的通用模式,在训练和推理阶段,比较输入图像和记忆池中的样本之间的差异,为异常区域的定位提供有用的信息。

斯人若彩虹,遇上方知有! 4841

【现代人形机器人:从物理建模到大模型驱动的控制与学习】第1章 机器人建模回顾

本章建立读者进行后续控制 / 优化 / 学习工作的数学与计算基础。内容分为三大块:刚体运动学:位姿表示、坐标变换、旋转参数与李代数/李群(指数映射、twist)多关节机构的正/逆运动学:DH 与 POE 两种建模、雅可比矩阵推导、数值/解析逆解方法与奇异性问题约束动力学:拉格朗日公式、牛顿—欧拉递归算法、接触/冲击模型、受约束系统的方程(拉格朗日乘子与互补性条件)每一节同时给出与练习题。假设读者已具备线性代数(矩阵、特征分解、SVD)、多变量微积分与基础力学(牛顿第二定律)知识。

u012133341的博客 186

Spring高手之路17——动态代理的艺术与实践

本文深入分析了JDK和CGLIB两种动态代理技术在Spring框架中的应用。讨论了动态代理的基础概念,通过实例展示了如何实现和应用这两种方法,并比较了它们的性能差异及适用场景。进一步,探讨了在动态代理中实现熔断限流和日志监控的策略,以及如何利用动态代理优化Spring应用的设计和功能。

卓越无关环境,保持空杯心态——靡不有初,鲜克有终 1万+

RK3568平台开发系列讲解(NPU篇)什么是RKNPU

📢本篇章将介绍RKNPU。

内核笔记 4359

Java动态代理与CGLib

Java帝国之动态代理 CGLib:从兄弟到父子-动态代理在民间是怎么玩的? 以上两篇文章引用自微信公众号:码农翻身 Java动态代理 深度详解 以上文章引用博客园:陈树义 转载于:https://www.cnblogs.com/NEWHOM/p/7878242.html...

weixin_34356138的博客 86

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

告别2017,码农翻身全年文章精华

时间过得真快,转眼间2017年就结束了!感谢大家一年来的陪伴、支持和鼓励!这里是2017年全年码农翻身文章精华, 点击标题阅读, 欢迎转发分享。 如果觉得不过瘾的话,一定要逛逛《码农翻身2016年文章精华》, 那里有更多有趣的技术故事。大话编程一个故事讲完httpsC老头和Java小子的硬盘夜话我是一个函数操作系统是个大骗子?90后“老头儿”和00后Go小子的硬盘夜话爱炫耀的数据库老头儿浏览器:一...

Robin022的专栏 396

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

我把这两年的精华文章都整理出来了

应读者要求,把码农翻身的所有文章做了一个分类,方便大家出查找,欢迎转发,分享。该目录持续更新中,在公众号首页发送消息“目录”,可以看到最新版。想通过关键字搜索的,可以点...

码农翻身 770

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

《码农翻身》17-18年精华文章

原文链接 计算机基础我是一个线程TCP/IP 之 大明邮差TCP/IP 之 大明内阁TCP/IP 之 蓟辽督师CPU 阿甘CPU 阿甘之烦恼我是一个网卡我是一个路由器我是一个进程我是一块硬盘(上)我是一块硬盘(下)我是一个键盘张大胖的socket张大胖学递归操作系统是个大骗子?编程世界的那把锁加锁还是不加锁,这是...

lovego123的博客 1278

动态代理之 cglib 实现

(尊重劳动成果,转载请注明出处:https://blog.youkuaiyun.com/qq_25827845/article/details/87513102冷血之心的博客) 目录 前言: 正文: AOP(面向切面编程) JDK动态代理 cglib实现动态代理 cglib包结构: cglib动态代理相关的基础类: cglib动态代理Demo 总结: 前言:         这篇文...

冷血之心的博客 9288

【cglib实现动态代理】

cglib是是第三方的工具库。其原理是继承,cglib通过继承目标类,创建他的子类,在子类当中重写父类的相关方法,实现功能的增强。

edwer93的博客 1205

CGLIB原理

CGLIB 动态代理基于子类继承,通过字节码操作技术(如 ASM)动态生成代理类。它可以在运行时增强类的功能,使得开发者无需修改原有类的代码就能实现日志、权限校验等功能。虽然 CGLIB 在性能上有一定的开销,但其强大的代理能力使得它在 Spring 等框架中得到了广泛应用。

weixin_54574094的博客 2164

CGLIB动态代理

文章目录概述CGLIB组织结构CGLIB动态代理示例分析代理类分析FastClass 机制MethodProxy.invoke(Object obj, Object[] args)分析CGLIB动态代理碰到的问题问题1:异常Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/Type问题2问题3总结 概述 CGLIB是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,

FromZeroJiYuan的博客 4186

动态代理之cglib代理

看了 上云 老师的视频,整理下。

qq_37342720的博客 703

CGLIB 动态代理

目录 CGLIB 动态代理 简单结构: 添加依赖 定义类 CGLIB 动态代理 JDK的动态代理机制只能代理实现了接口的类。而不能实现接口的类就不能使用JDK的动态代理,CGLIB是针对类来实现代理的,它的原理是对指定目标类生成一个子类,并覆盖其中的方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。 简单结构: 实现原理:继承思想 代理类继承目标类,重写目标类中的方法, CGLIB像是一个拦截器,在调用我们的代...

m0_61609890的博客 7356
上一篇: Java EE要死掉了?
下一篇: 小白科普:悲观锁和乐观锁
码农翻身
码农翻身 《码农翻身》作者 《码农翻身》作者
博客等级 码龄8年 3万+粉丝 1084原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值