jdk动态代理和cglib动态代理对比

jdk动态代理和cglib动态代理对比:

CGLIB 和 JDK 动态代理都可以用来在运行时生成代理对象

1. 基本概念

  • JDK 动态代理:只代理接口(interface),无法代理类。它使用 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现动态代理。
  • CGLIB 动态代理:可以代理类和接口。它通过生成目标类的子类来创建代理对象,因此可以代理没有实现接口的类。

2. 使用场景

  • JDK 动态代理:适用于目标对象实现了一个或多个接口的情况。Spring AOP 默认使用 JDK 动态代理,如果目标对象没有实现接口,则使用 CGLIB。
  • CGLIB 动态代理:适用于目标对象没有实现接口或者需要代理类而不是接口的情况。

3. 性能

  • JDK 动态代理:由于使用了反射机制,性能相对较低,但对于简单接口的代理,性能差异不明显。
  • CGLIB 动态代理:通过生成字节码来创建代理对象,性能比 JDK 动态代理更高,但是生成字节码的开销较大。

 4. 优缺点总结

  • JDK 动态代理

    • 优点:简单,直接使用 JDK 提供的 API,无需额外依赖。
    • 缺点:只能代理接口,性能较低。
  • CGLIB 动态代理

    • 优点:可以代理类和接口,性能较高。
    • 缺点:需要额外的 CGLIB 库,生成字节码的开销较大,无法代理 final 类和方法。

jdk动态代理:

1. 被代理的接口和实现类:

public interface Subject {void doSomething();
}public class RealSubject implements Subject {@Overridepublic void doSomething() {System.out.println("Doing something in RealSubject");}
}

2. 创建 InvocationHandler 实现类: 

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler {private final Object target;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method execution");Object result = method.invoke(target, args);System.out.println("After method execution");return result;}
}

3. 使用 Proxy 创建代理对象: 

import java.lang.reflect.Proxy;public class JdkProxyDemo {public static void main(String[] args) {Subject realSubject = new RealSubject();Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new MyInvocationHandler(realSubject));proxy.doSomething();}
}

cglib动态代理使用步骤

CGLIB(Code Generation Library)是一个强大的高性能代码生成库,它可以在运行时动态生成字节码。CGLIB 常用于创建代理对象,特别是在 Spring 框架中,用于 AOP(面向切面编程)

1. 添加 CGLIB 依赖项:
如果你使用的是 Maven,可以在 pom.xml 中添加以下依赖项:

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

2. 被代理的类

public class RealSubject {private String field;public String getField() {return field;}public void setField(String field) {this.field = field;}public void doSomething() {System.out.println("Doing something in RealSubject");}
}

3. 创建 MethodInterceptor:

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("Before method execution");Object result = proxy.invokeSuper(obj, args);System.out.println("After method execution");return result;}
}

4.创建代理对象:

import net.sf.cglib.proxy.Enhancer;public class CglibProxyDemo {public static void main(String[] args) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(RealSubject.class);enhancer.setCallback(new MyMethodInterceptor());RealSubject proxy = (RealSubject) enhancer.create();proxy.doSomething();}
}

RealSubject 是被代理的类,MyMethodInterceptor 实现了 MethodInterceptor 接口,用于在方法执行前后添加额外的逻辑。Enhancer 类用于创建代理对象。

运行 CglibProxyDemo 类时,你会看到如下输出:

cglib jdk17 的问题:

jdk17 需要增加如下配置,否则会 报错:

--add-opens=java.base/java.lang=ALL-UNNAMED

在 JDK 9 及其之后的版本(包括 JDK 17)中,Java 引入了模块系统(Project Jigsaw),这使得访问某些内部 API 和模块变得更加严格。--add-opens 参数允许你在运行 Java 应用时开放特定的模块和包给未命名模块(通常是类路径上的代码),以便它们可以进行深层次的反射操作。

报错信息:

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @4cdf35a9at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)at net.sf.cglib.core.ReflectUtils$1.run(ReflectUtils.java:61)at java.base/java.security.AccessController.doPrivileged(AccessController.java:569)at net.sf.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:52)at net.sf.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243)at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:332)... 13 more

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

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

相关文章

给vscode的新项目选择虚拟环境

按照通常的步骤新建了.vscode文件并生成了launch.json&#xff0c;都是通过左栏的调试按钮里的create a json file&#xff0c;但是 运行时还是没有识别&#xff0c;之后看到下面的这个链接里&#xff0c;图中是在>之后选择的环境&#xff0c;于是&#xff1a; ctrlG出现搜索…

攻破 Kioptix Level 1 靶机

找教程然后自己练习&#xff0c;论菜狗的自我修养 基本步骤 1.确定目标IP 2.扫描端口&#xff0c;服务&#xff0c;版本信息&#xff0c;漏洞信息 3.查找漏洞可利用脚本 4.运行脚步 一、信息获取 arp-scan -l nmap -sS -p- -sV -sC -A --min-rate5000 192.168.5.130 二、查…

b站ip属地评论和主页不一样怎么回事

在浏览B站时&#xff0c;细心的用户可能会发现一个有趣的现象&#xff1a;某些用户的评论IP属地与主页显示的IP属地并不一致。这种差异引发了用户的好奇和猜测&#xff0c;究竟是什么原因导致了这种情况的发生呢&#xff1f;本文将对此进行深入解析&#xff0c;帮助大家揭开这一…

如何使用fetch函数获取多个数据并同时使用(在嵌套的fetch函数之间传递数据)

&#xff08;一&#xff09;问题描述 需要读取多个数据&#xff0c;也就是有多个fetch函数&#xff0c;但是这些数据又需要同时用。由于fetch是异步的&#xff0c;因此每个fetch单独进行是没有办法同时获得数据的&#xff0c;此时有两种可行的方式。 &#xff08;二&#xff…

音视频入门基础:MPEG2-PS专题(2)——使用FFmpeg命令生成ps文件

通过FFmpeg命令可以将mp4文件转换为ps文件。由于ps文件对应的FFInputFormat结构为&#xff1a; const FFInputFormat ff_mpegps_demuxer {.p.name "mpeg",.p.long_name NULL_IF_CONFIG_SMALL("MPEG-PS (MPEG-2 Program Stream)"),.p.flags …

帝国cms电脑pc站url跳转到手机站url的方法

本文讲解一下帝国cms电脑网站跳转到手机动态网站和手机静态网站的方法,笔者以古诗词网 www.gushichi.com为例&#xff0c;为大家介绍操作步骤。方法一&#xff1a;帝国pc站跳转到手机静态站 1、假设我们有帝国cms 电脑网站www.XXX.com&#xff0c;手机网站m.XXX.com &#xf…

【数据结构与算法】单向链表

一、什么是链表 链表由一系列节点组成&#xff0c;每个节点都包含一个 data 域&#xff08;存放数据&#xff09;和一个 next 域&#xff08;指向下一节点&#xff09;。链表中的节点可以按照任意顺序存放在内存中&#xff0c;它们之间并不连续。每个节点都记录了下一个节点的地…

【AI大模型系列】常用的提示词框架(二)

目录 一、ICIO框架 1.1 ICIO框架组成 1.2 ICIO框架案例 二、CRISPE框架 2.1 CRISPE框架组成 2.2 CRISPE框架案例 三、BROKE框架 3.1 BROKE框架组成 3.2 BROKE框架案例 四、RASCEF框架 4.1 RASCEF框架组成 4.2 RASCEF框架案例 一、ICIO框架 1.1 ICIO框架组成 Instru…

【Golang 面试题】每日 3 题(八)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

struct udp_sock

这个struct udp_sock结构体是Linux内核网络栈中用于表示一个UDP套接字的数据结构。它继承自struct inet_sock,这意味着它包含了所有IPv4或IPv6套接字共享的基础信息和函数指针。下面是对struct udp_sock中一些关键成员的解释: struct inet_sock inet;:这是udp_sock结构体的第…

【计组】例题课后题

第一章 计算机如何区分指令和数据&#xff1f; 一般来讲&#xff0c;在取指周期中从内存读出的信息是指令流,它流向控制器&#xff1b;而执行周期中从内存读出的信息流是数据流,它由内存流向运算器。 从存放位置看&#xff0c;从代码段取出的是指令流&#xff0c;从数据…

C#数学相关开发性能优化方法

本文Github地址&#xff1a;CSharp-MathOptimization.md 华为公司的C语言编程规范在开头就强调了&#xff1a; 一般情况下&#xff0c;代码的可阅读性高于性能&#xff0c;只有确定性能是瓶颈时&#xff0c;才应该主动优化。 本文讲述的方法没有经过大项目和大公司的检验&…

一网多平面

“一网多平面”是一种网络架构概念&#xff0c;具体指的是在一张物理网络之上&#xff0c;逻辑划分出“1N”个平面。以下是对“一网多平面”的详细解释&#xff1a; 定义与构成 01一网多平面 指的是在统一的物理网络基础设施上&#xff0c;通过逻辑划分形成多个独立的网络平面…

跨语言数据格式标准化在 HarmonyOS 开发中的实践

文章目录 前言数据格式标准化的意义数据传递中的痛点标准化的优势 JSON 与 Protocol Buffers 的比较JSONProtocol Buffers HarmonyOS 跨语言数据传递示例示例代码&#xff1a;定义 Protocol Buffers 消息格式生成 Java 和 C 代码示例代码&#xff1a;Java 端序列化与传递数据C …

【Python】基于界面库PyQt5+Qt Dsigner的环境配置和界面绘制

目录 一 安装PyQt5以及PyQt5-tools 二 配置外部开发工具 三 使用Qt Designer设计界面 四 使用PyUIC将ui文件转换为py文件 五 CU分离实现逻辑代码 一 安装PyQt5以及PyQt5-tools 之前做的一些Python脚本、软件都是基于 Tkinter 实现的&#xff0c;其中界面的设计布局是很头疼…

Java读取InfluxDB数据库的方法

本文介绍基于Java语言&#xff0c;读取InfluxDB数据库的方法&#xff0c;包括读取InfluxDB的所有数据库&#xff0c;以及指定数据库中的measurement、field、tag等。 首先&#xff0c;创建一个Java项目&#xff0c;用于撰写代码。如果大家是基于IDEA来创建项目&#xff0c;则可…

嵌入式驱动开发详解7(并发、竞争、中断)

文章目录 前言并发和竞争原子操作自旋锁信号量互斥体 中断中断简介中断API上半部和下半部设备树分析中断号获取源码 后续参考文献 前言 中断会引起线程的切换&#xff0c;并发和竞争也是对线程切换的一种灵活保护和处理&#xff0c;因此这里将中断和并发与竞争放在一块讲解说明…

渗透测试常用术语总结

一、攻击篇 1&#xff0e;攻击工具 肉鸡 所谓“肉鸡”是一种很形象的比喻&#xff0c;比喻那些可以被攻击者控制的电脑、手机、服务器或者其他摄像头、路由器等智能设备&#xff0c;用于发动网络攻击。 例如在2016年美国东海岸断网事件中&#xff0c;黑客组织控制了大…

11.MySQL视图特性

目录 视图基本使用视图规则和限制 视图 视图是一个虚拟表, 其内容有查询定义. 同真实的表一样, 视图包含一系列带有名称的列和行数据. 视图的数据变化会影响到基表, 基表的数据变化也会影响到视图, 这个视图和刚刚讲的ReadView之间没有任何关系. 基本使用 创建视图: create vi…

【RabbitMQ高级篇】消息可靠性问题(1)

目录 1.消息可靠性 1.1.生产者消息确认 1.1.1.修改配置 1.1.2.定义Return回调 1.1.3.定义ConfirmCallback 1.2.消息持久化 1.2.1.交换机持久化 1.2.2.队列持久化 1.2.3.消息持久化 1.3.消费者消息确认 1.3.1.演示none模式 1.3.2.演示auto模式 1.4.消费失败重试机制…