动态代理应用非常的广泛,在各种开源的框架中都能看到他们的身影,比如spring中的aop使用动态代理增强,mybatis中使用动态代理生成mapper,动态代理主要有jdk和cglib两种方式,今天来学习下这两种方式的实现,以及它们的优缺点
动态代理:是使用反射和字节码的技术,在运行期创建指定接口或类的子类,以及其实例对象的技术,通过这个技术可以无侵入的为代码进行增强
基于 spring boot + mybatis plus + vue & element 实现的后台管理系统 + 用户小程序,支持 rbac 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
一、jdk实现的动态代理
1、解析
jdk实现的动态代理由两个重要的成员组成,分别是proxy、invocationhandler
proxy: 是所有动态代理的父类,它提供了一个静态方法来创建动态代理的class对象和实例
invocationhandler: 每个动态代理实例都有一个关联的invocationhandler,在代理实例上调用方法是,方法调用将被转发到invocationhandler的invoke方法
2、简单看下jdk的动态代理的原理图
3、代码实现
现在模拟一个用户注册的功能,动态代理对用户的注册功能进行增强,会判断用户名和密码的长度,如果用户名<=1和密码 0 && args[0] instanceof user) { user user = (user)args[0]; //进行增强判断 if (user.getname().length() <= 1) { throw new runtimeexception(用户名长度必须大于1); } if (user.getpassword().length() 0 && args[0] instanceof user) { user user = (user)args[0]; //进行增强判断 if (user.getname().length() <= 1) { throw new runtimeexception(用户名长度必须大于1); } if (user.getpassword().length() <= 6) { throw new runtimeexception(密码长度必须大于6); } } object result = method.invoke(realobject, args); system.out.println(用户注册成功...); return result; } }clienttest.javapackage com.taolong.cglib; import com.taolong.user; import net.sf.cglib.proxy.enhancer; public class clienttest { public static void main(string[] args) { user user = new user(); user.setname(hongtaolong); user.setpassword(hong); user.setage(23); //被代理的对象 userserviceimplcglib delegate = new userserviceimplcglib(); userservicecglibinterceptor serviceinterceptor = new userservicecglibinterceptor(delegate); enhancer enhancer = new enhancer(); enhancer.setsuperclass(delegate.getclass()); enhancer.setcallback(serviceinterceptor); //动态代理类 userserviceimplcglib cglibproxy = (userserviceimplcglib)enhancer.create(); system.out.println(动态代理类父类:+cglibproxy.getclass().getsuperclass()); cglibproxy.adduser(user); }} 运行结果:
这里顺便打印了动态代理类的父类,接下来我们将它的父类userserviceimplcglib的adduser方法用final修饰,看看是否会被增强
userserviceimplcglib.java
package com.taolong.cglib; import com.taolong.user; public class userserviceimplcglib { final void adduser(user user) { system.out.println(cglib...正在注册用户,用户信息为:+user); }} 运行结果:
总结一下
1、jdk原声动态代理时java原声支持的、不需要任何外部依赖、但是它只能基于接口进行代理(因为它已经继承了proxy了,java不支持多继承)
2、cglib通过继承的方式进行代理、无论目标对象没有没实现接口都可以代理,但是无法处理final的情况(final修饰的方法不能被覆写)
Abb机器人示教器可编程按钮的配置方法
探究人工智能在保险公司的应用
现代PCB设计人员的电子设计自动化
PCB焊接中冷焊与伪焊接的区别
3mm x 3mm线性电流传感器IC的的感应电阻运算放大器解决方案
Java动态代理:JDK和CGLIB两种方式实现及优缺点分析
OPPO华为新机硬刚,品牌质量到底哪家更强?
新能源汽车已连续多月呈现爆发式增长
全球互联网通信云厂商融云完成数亿人民币D轮融资
高通收购恩智浦后,将主导汽车芯片市场?
iPhone 12 Pro具有与标准iPhone 12相同的6.1英寸显示屏
单片机与嵌入式的转化
INS322-2B工业级组合导航定位系统优势特点
据说折叠屏Razr定价很高,在美国要1500美元
增加LED附加值 打造智能化照明
贸易战、科技战何去何从?
或许这就是对Flyme 6最犀利的点评: 我可能用了假iOS 魅族流畅媲美ios系统
百度正式宣布将收购国内直播业务—YY直播
竞逐智慧医疗大饼 Maxim智能可穿戴IC方案取得重大进展
小米意在互联网金融第三极 强势推进互联网金融