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

动态代理jdk的Proxy与Spring的CGlib

动态代理jdk的Proxy与Spring的CGlib

文章目录

  • 动态代理jdk的Proxy与Spring的CGlib
  • 1. 为什么要使用动态代理?
  • 2. JDK Proxy 动态代理面向接口的动态代理
  • 3. CGlib动态代理
  • 4. 两个动态代理的区别

1. 为什么要使用动态代理?

动态代理:在不改变原有代码的情况下上进行对象功能增强 使用代理对象代替原来的对象完成功能 进而达到拓展功能的目的

2. JDK Proxy 动态代理面向接口的动态代理

特点:

  1. 一定要有接口和实现类的存在 代理对象增强的是实现类 在实现接口的方法重写的方法
  2. 生成的代理对象只能转换成 接口的,不能转换成 被代理类
  3. 代理对象只能增强接口中定义的方法 实现类中其他和接口无关的方法是无法增强的
  4. 代理对象只能读取到接口中方法上的注释 不能读取到实现类方法上的注解

使用方法:

public class Test01 {public static void main(String[] args) {Person person=new Student("xjz_2002");// 通过Porxy动态代理获得一个代理对象,在代理对象中,对某个方法进行增强
//        ClassLoader loader,被代理的对象的类加载器ClassLoader classLoader = dinner.getClass().getClassLoader();
//        Class<?>[] interfaces,被代理对象所实现的所有接口Class[] interaces= dinner.getClass().getInterfaces();
//        InvocationHandler h,执行处理器对象,专门用于定义增强的规则InvocationHandler handler = new InvocationHandler(){// invoke 当我们让代理对象调用任何方法时,都会触发invoke方法的执行public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                Object proxy, 代理对象
//                Method method,被代理的方法
//                Object[] args,被代理方法运行时的实参Object res=null;if(method.getName().equals("eat")){System.out.println("饭前洗手");// 让原有的eat的方法去运行res =method.invoke(dinner, args);System.out.println("饭后刷碗");}else{// 如果是其他方法,那么正常执行就可以了res =method.invoke(dinner, args);}return res;}};Dinner dinnerProxy =(Dinner) Proxy.newProxyInstance(classLoader,interaces,handler);//dinnerProxy.eat("馒头");dinnerProxy.drink();}
}
interface Person{void eat(String foodName);void drink();
}
class Student implements Person{private String name;public Student(String name) {this.name = name;}@Overridepublic void eat(String foodName) {System.out.println(name+"正在宿舍吃"+foodName);}@Overridepublic void drink( ) {System.out.println(name+"正在喝可乐");}
}
class Teacher implements Person{private String name;public Teacher(String name) {this.name = name;}@Overridepublic void eat(String foodName) {System.out.println(name+"正在食堂吃"+foodName);}@Overridepublic void drink( ) {System.out.println(name+"正在喝茶");}
}

3. CGlib动态代理

cglib动态代理模式是面向父类

特点:

  1. 面向父类的和接口没有直接关系
    • 不仅可以增强接口中定义的方法还可以增强其他方法
    • 可以读取父类中方法上的所有注解
  2. 使用实例
public class Test02 {@Testpublic void testCglib(){Person person =new Person();// 获取一个Person的代理对象// 1 获得一个Enhancer对象Enhancer enhancer=new Enhancer();// 2 设置父类字节码enhancer.setSuperclass(person.getClass());// 3 获取MethodIntercepter对象 用于定义增强规则MethodInterceptor methodInterceptor=new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {/*Object o,  生成之后的代理对象 personProxyMethod method,  父类中原本要执行的方法  Person>>> eat()Object[] objects, 方法在调用时传入的实参数组MethodProxy methodProxy  子类中重写父类的方法 personProxy >>> eat()*/Object res =null;if(method.getName().equals("eat")){// 如果是eat方法 则增强并运行System.out.println("饭前洗手");res=methodProxy.invokeSuper(o,objects);System.out.println("饭后刷碗");}else{// 如果是其他方法 不增强运行res=methodProxy.invokeSuper(o,objects); // 子类对象方法在执行,默认会调用父类对应被重写的方法}return res;}};// 4 设置methodInterceptorenhancer.setCallback(methodInterceptor);// 5 获得代理对象Person personProxy = (Person)enhancer.create();// 6 使用代理对象完成功能personProxy.eat("馒头");}
}
class Person  {public Person( ) {}public void eat(String foodName) {System.out.println("xjz_2002正在吃"+foodName);}
}

4. 两个动态代理的区别

  1. JDK动态代理是面向接口的,只能增强实现类中接口中存在的方法。CGlib是面向父类的,可以增强父类的所有方法
  2. JDK得到的对象是JDK代理对象实例,而CGlib得到的对象是被代理对象的子类

相关文章:

  • Python之Django项目的功能配置
  • 音视频的编码格式与封装格式
  • 图像识别SLIC、Haralick texture features(自备)
  • 3.1 C语言之控制流语句
  • 【四】记一次关于架构设计从0到1的讨论
  • prometheus二进制安装
  • 【Flink-Kafka-To-ClickHouse】使用 Flink 实现 Kafka 数据写入 ClickHouse
  • SSTI模板注入基础(Flask+Jinja2)
  • 前端验收测试驱动开发
  • 高并发情况下,数据库与缓存数据不一致问题
  • WorkPlus超级APP助力企业节省IT人力成本,实现快速移动化
  • ARM学习(24)Can的高阶认识和错误处理
  • WPScan安全建议和防护
  • ArrayList源码学习笔记(3)
  • Vue 的两种实现:VSCode 中配置 vue 模板快捷方式的过程
  • hexo+github搭建个人博客
  • .pyc 想到的一些问题
  • canvas绘制圆角头像
  • Consul Config 使用Git做版本控制的实现
  • CSS实用技巧干货
  •  D - 粉碎叛乱F - 其他起义
  • iOS 颜色设置看我就够了
  • java小心机(3)| 浅析finalize()
  • js中forEach回调同异步问题
  • Spring Cloud Feign的两种使用姿势
  • 二维平面内的碰撞检测【一】
  • 聚类分析——Kmeans
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 前端面试题总结
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 原生 js 实现移动端 Touch 滑动反弹
  • #NOIP 2014#Day.2 T3 解方程
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (04)odoo视图操作
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (力扣)1314.矩阵区域和
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (十一)手动添加用户和文件的特殊权限
  • (小白学Java)Java简介和基本配置
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)创业家杂志:UCWEB天使第一步
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .net/c# memcached 获取所有缓存键(keys)
  • .NET文档生成工具ADB使用图文教程
  • @selector(..)警告提示
  • [ 蓝桥杯Web真题 ]-布局切换
  • [1]-基于图搜索的路径规划基础
  • [20161214]如何确定dbid.txt
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [Android] 修改设备访问权限
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现