动态代理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得到的对象是被代理对象的子类

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

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

相关文章

如何通过UMC配置外围组件

随着云计算技术的不断发展&#xff0c;在信息化建设模式上云是大势所趋。对于企业而言&#xff0c;已建立的内部集成并不能支撑其快速搭建开发环境、快速部署集群服务&#xff0c;并且动态水平扩展对多组织情况许可费用高昂、没有敏捷快速迭代机制&#xff0c;导致开发完毕就落…

增量式旋转编码器在STM32平台上的应用

背景 旋钮是仪器仪表上一种常见的输入设备&#xff0c;它的内部是一个旋转编码器&#xff0c;知乎上的这篇科普文章对其工作原理做了深入浅出的介绍。 我们公司的功率分析仪的前面板也用到了该类设备&#xff0c;最近前面板的MCU从MSP430切换成了STM32&#xff0c;因此我要将…

Could not resolve com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.28.

1、首先进入阿里云maven仓库&#xff0c;在搜索栏输入无法下载的依赖名称&#xff0c;查询现有版本号&#xff0c;可以看到这里有2.9.34。 2、在build.gradle(Project)的buildscript闭包下替换为阿里云maven仓库&#xff1a; maven { url https://www.jitpack.io } maven { u…

基于 ACK One 实现简单的跨云协同,让业务管理更高效

作者&#xff1a;庄宇 本文根据 2023 云栖大会现场分享实录整理 2 年前的云栖大会&#xff0c;我们发布分布式云容器平台 ACK One&#xff0c;随着 2 年的发展&#xff0c;很高兴看到 ACK One 在混合云&#xff0c;分布式云领域帮助到越来越多的客户&#xff0c;今天给大家汇报…

使用 IntelliJ IDEA 创建一个 Java 文件并运行

启动 IntelliJ IDEA 并创建一个新项目: 打开 IntelliJ IDEA。 选择 “Create New Project”&#xff08;创建新项目&#xff09;。 在左侧&#xff0c;选择 “Java”&#xff0c;确保已经选择了正确的 JDK 版本。 点击 “Next”&#xff08;下一步&#xff09;。 可以跳过额外…

中心性算法归纳

中心性算法不仅是在我所学习的计算机网络当中起很重要的作用&#xff0c;在交通网络、社交网络、信息网络、神经网络当中也有很多的应用例子。今天我在这里总结一下场景的几种中心性算法。 参考文献 Python NetworkX库 偏心中心性&#xff08;Eccentricity Centrality&#x…

银河麒麟v10 rpm安装包 安装mysql 8.35

银河麒麟v10 rpm安装包 安装mysql 8.35 1、卸载mariadb2、下载Mysql安装包3、安装Mysql 8.353.1、安装Mysql 8.353.3、安装后配置 1、卸载mariadb 由于银河麒麟v10系统默认安装了mariadb 会与Mysql相冲突&#xff0c;因此首先需要卸载系统自带的mariadb 查看系统上默认安装的M…

网络安全行业术语

病毒 是在计算机程序中插入的破坏计算机功能或者数据的代码&#xff0c;能影响计算机使用&#xff0c;能自我复制的一组计算机指令或者程序代码。 抓鸡 利用使用大量的程序的漏洞&#xff0c;使用自动化方式获取肉鸡的行为&#xff0c;即设法控制电脑&#xff0c;将其沦为肉…

C++ 牛群 字符串类型简单统计

约翰有 n 头奶牛。 每头奶牛的品种由一个小写字母表示&#xff0c;不同奶牛的品种可能不同。 请问&#xff0c;能否将这些奶牛分为两个非空的牛群&#xff0c;并使得每个牛群都恰好包含两种奶牛。 例如&#xff0c;如果一共有 5 头奶牛&#xff0c;品种依次为 aabcc&#xf…

平方矩阵()

平方矩阵1 平方矩阵2 曼哈顿距离 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring>using namespace std;const int N 110;int n; int a[N][N];int main() {while(cin >> n, n){for (int i 0; i < n; i )fo…

采用SpringBoot框架+原生HTML、JS前后端分离模式开发和部署的电子病历编辑器源码(电子病历评级4级)

概述&#xff1a; 电子病历是指医务人员在医疗活动过程中,使用医疗机构信息系统生成的文字、符号、图表、图形、数据、影像等数字化信息,并能实现存储、管理、传输和重现的医疗记录,是病历的一种记录形式。 医院通过电子病历以电子化方式记录患者就诊的信息&#xff0c;包括&…

网络协议-BIO实战和NIO编程

网络通信编程基本常识 原生JDK网络编程-BIO 原生JDK网络编程-NIO Buffer 的读写 向 Buffer 中写数据 写数据到 Buffer有两种方式: 1. 读取 Channel写到 Buffer。 2.通过 Buffer 的 put0方法写到 Buffer 里。 从 Channel 写到 Buffer …

力扣经典面试题——搜索二维矩阵(两次二分搜索)

https://leetcode.cn/problems/search-a-2d-matrix/description/?envTypestudy-plan-v2&envIdtop-100-liked 思路&#xff1a;先按行二分&#xff0c;再按列进行二分。即先找到对应的行&#xff0c;再找对应的列。 对于这种判断是否存在某个数&#xff0c;记得while(left…

[JS设计模式]Mixin Pattern

Mixin是一个对象&#xff0c;我们可以使用它来为另一个对象或类添加可重用的功能&#xff0c;而无需使用继承。我们不能单独使用mixins:它们的唯一目的是在没有继承的情况下向对象或类添加功能。 假设对于我们的应用程序&#xff0c;我们需要创建多个狗。然而&#xff0c;我们…

Linux系统中跟TCP相关的系统配置项

TCP连接保活 参考 《Nginx(三) 配置文件详解 - 基础模块》3.18章节 net.ipv4.tcp_keepalive_intvl&#xff1a;设置TCP两次相邻探活检测的间隔时间。默认75秒&#xff0c;单位是秒&#xff0c;对应配置文件/proc/sys/net/ipv4/tcp_keepalive_intvl&#xff1b;net.ipv4.tcp_kee…

form-data、x-www-form-urlencoded、raw 和 binary

在 Postman 中&#xff0c;有四种常见的请求体格式&#xff0c;分别是 form-data、x-www-form-urlencoded、raw 和 binary。它们的区别如下&#xff1a; form-data form-data 格式通常用于上传文件或二进制数据。在 Postman 中&#xff0c;你可以通过选择 Body 标签页&#x…

【错误记录/js】保存octet-stream为文件后数据错乱

目录 说在前面场景解决方式其他 说在前面 后端&#xff1a;go、gin浏览器&#xff1a;Microsoft Edge 120.0.2210.77 (正式版本) (64 位) 场景 前端通过点击按钮来下载一些文件&#xff0c;但是文件内容是一些非文件形式存储的二进制数据。 后端代码 r : gin.Default()r.Stat…

MyBatis见解2

5.MyBatis的原始Dao开发-了解 使用Mybatis开发Dao&#xff0c;通常有两个方法&#xff0c;即原始Dao开发方式和Mapper接口代理开发方式。而现在主流的开发方式是接口代理开发方式&#xff0c;这种方式总体上更加简便。我们的课程讲解也主要以接口代理开发方式为主。在第4节已经…

项目功能需求

需求分解做法记录 功能&#xff1a;先按名称分组然后&#xff0c;组内从低到高排序&#xff0c;然后每组排序 做法一&#xff1a; List<CruiseDetailOutputDto> result new ArrayList<CruiseDetailOutputDto>();List<CruiseDetailOutputDto> journeyCrui…

冒泡排序之C++实现

描述 冒泡排序算法是一种简单的排序算法&#xff0c;它通过将相邻的元素进行比较并交换位置来实现排序。冒泡排序的基本思想是&#xff0c;每一轮将未排序部分的最大元素逐个向右移动到已排序部分的最右边&#xff0c;直到所有元素都按照从小到大的顺序排列。 冒泡排序的算法…