揭秘!JDK动态代理VS CGLIB:一场关于Java代理界的‘宫心计’,你站哪队?

简介: 【8月更文挑战第24天】Java 动态代理是一种设计模式,允许在不改动原类的基础上通过代理类扩展功能。主要实现方式包括 JDK 动态代理和 CGLIB。前者基于接口,利用反射机制在运行时创建代理类;后者采用继承方式并通过字节码技术生成子类实现类的代理。两者在实现机制、性能及适用场景上有明显差异。JDK 动态代理适用于有接口的场景,而 CGLIB 更适合代理未实现接口的类,尽管性能更优但存在一些限制。开发者可根据需求选择合适的代理方式。

Java 动态代理是 Java 编程中常用的一种设计模式,它允许开发者在不修改原有类代码的情况下,通过代理类对原有类的功能进行扩展。JDK 动态代理和 CGLIB 是两种主要的实现方式,它们在实现机制、性能表现以及适用场景上存在显著差异。

JDK 动态代理
JDK 动态代理是 Java 标准库提供的一种基于接口的代理机制。它利用 Java 的反射机制,在运行时动态地创建代理类,这些代理类实现了被代理的接口,并通过 InvocationHandler 来处理方法的调用。

示例代码
以下是一个简单的 JDK 动态代理示例:

java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义一个接口
interface MyInterface {
void doSomething();
}

// 实现接口的目标类
class MyTarget implements MyInterface {
@Override
public void doSomething() {
System.out.println("Target method executed.");
}
}

// 自定义 InvocationHandler
class MyInvocationHandler implements InvocationHandler {
private Object target;

public MyInvocationHandler(Object target) {  
    this.target = target;  
}  

@Override  
public 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;  
}  

}

// 创建代理对象并调用方法
public class JDKProxyDemo {
public static void main(String[] args) {
MyInterface target = new MyTarget();
MyInvocationHandler handler = new MyInvocationHandler(target);
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler
);
proxy.doSomething(); // 输出代理逻辑
}
}
CGLIB 动态代理
CGLIB(Code Generation Library)是一个开源项目,通过继承的方式来实现动态代理。它可以在运行时动态地生成被代理类的子类,从而允许代理没有实现接口的类。CGLIB 使用 ASM 字节码框架来生成代理类,因此其性能通常比 JDK 动态代理更高。

示例代码
虽然 CGLIB 的使用通常需要借助第三方库(如 Spring),但以下是一个简化的概念性示例,展示其工作原理:

java
// 注意:实际使用CGLIB时,通常不会直接编写如下代码,而是通过框架如Spring AOP来使用
// 假设有一个没有接口的类
class MyClass {
public void doSomething() {
System.out.println("Original method executed.");
}
}

// 假设的CGLIB代理类(实际由CGLIB生成)
class MyClassProxy extends MyClass {
@Override
public void doSomething() {
System.out.println("Before method execution.");
super.doSomething(); // 调用原始方法
System.out.println("After method execution.");
}
}

// 实际应用中,不会直接创建这个类,而是通过CGLIB API来动态生成
区别总结
实现机制:JDK 动态代理基于接口,通过反射机制实现;CGLIB 动态代理基于继承,通过字节码技术生成子类。
性能:由于 CGLIB 生成的代理类更底层,通常性能更高,但启动时间可能稍长。
适用场景:JDK 动态代理适用于接口代理;CGLIB 动态代理适用于类代理,特别是当类没有实现接口时。
限制:CGLIB 不能代理 final 方法和类,且在某些特殊场景(如 Android 开发)中可能有限制。
通过对比 JDK 动态代理和 CGLIB,开发者可以根据实际需求选择最适合的代理机制。

相关文章
|
16天前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
37 1
|
2天前
|
缓存 Java Maven
java: 警告: 源发行版 11 需要目标发行版 11 无效的目标发行版: 11 jdk版本不符,项目jdk版本为其他版本
如何解决Java项目中因JDK版本不匹配导致的编译错误,包括修改`pom.xml`文件、调整项目结构、设置Maven和JDK版本,以及清理缓存和重启IDEA。
8 1
java: 警告: 源发行版 11 需要目标发行版 11 无效的目标发行版: 11 jdk版本不符,项目jdk版本为其他版本
|
14天前
|
Oracle Java 关系型数据库
Linux下JDK环境的配置及 bash: /usr/local/java/bin/java: cannot execute binary file: exec format error问题的解决
如果遇到"exec format error"问题,文章建议先检查Linux操作系统是32位还是64位,并确保安装了与系统匹配的JDK版本。如果系统是64位的,但出现了错误,可能是因为下载了错误的JDK版本。文章提供了一个链接,指向Oracle官网上的JDK 17 Linux版本下载页面,并附有截图说明。
Linux下JDK环境的配置及 bash: /usr/local/java/bin/java: cannot execute binary file: exec format error问题的解决
|
1月前
|
Java API 开发者
【Java模块化新飞跃】JDK 22模块化增强:构建更灵活、更可维护的应用架构!
【9月更文挑战第9天】JDK 22的模块化增强为开发者构建更灵活、更可维护的应用架构提供了强有力的支持。通过模块化设计、精细的依赖管理和丰富的工具支持,开发者可以更加高效地开发和管理应用,提高应用的性能和可维护性。
60 10
|
1月前
|
安全 Java API
【性能与安全的双重飞跃】JDK 22外部函数与内存API:JNI的继任者,引领Java新潮流!
【9月更文挑战第7天】JDK 22外部函数与内存API的发布,标志着Java在性能与安全性方面实现了双重飞跃。作为JNI的继任者,这一新特性不仅简化了Java与本地代码的交互过程,还提升了程序的性能和安全性。我们有理由相信,在外部函数与内存API的引领下,Java将开启一个全新的编程时代,为开发者们带来更加高效、更加安全的编程体验。让我们共同期待Java在未来的辉煌成就!
53 11
|
1月前
|
监控 IDE Java
【Java性能调优新工具】JDK 22性能分析器:深度剖析,优化无死角!
【9月更文挑战第9天】JDK 22中的性能分析器为Java应用的性能调优提供了强大的支持。通过深度集成、全面监控、精细化分析和灵活报告生成等核心优势,性能分析器帮助开发者实现了对应用性能的全面掌控和深度优化。在未来的Java开发过程中,我们期待性能分析器能够继续发挥重要作用,为Java应用的性能提升贡献更多力量。
|
1月前
|
监控 Java 大数据
【Java内存管理新突破】JDK 22:细粒度内存管理API,精准控制每一块内存!
【9月更文挑战第9天】虽然目前JDK 22的确切内容尚未公布,但我们可以根据Java语言的发展趋势和社区的需求,预测细粒度内存管理API可能成为未来Java内存管理领域的新突破。这套API将为开发者提供前所未有的内存控制能力,助力Java应用在更多领域发挥更大作用。我们期待JDK 22的发布,期待Java语言在内存管理领域的持续创新和发展。
|
1月前
|
Java API 数据处理
【Java的SIMD革命】JDK 22向量API:释放硬件潜能,让Java应用性能飙升!
【9月更文挑战第7天】 JDK 22向量API的发布标志着Java编程语言在SIMD技术领域的重大突破。这一新特性不仅释放了现代硬件的潜能,更让Java应用性能实现了飙升。我们有理由相信,在未来的发展中,Java将继续引领编程语言的潮流,为开发者们带来更加高效、更加强大的编程体验。让我们共同期待Java在SIMD技术的推动下开启一个全新的性能提升时代!
|
1月前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!
|
12天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
32 2