揭秘!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,开发者可以根据实际需求选择最适合的代理机制。

相关文章
|
4月前
|
Java Spring
JDK动态代理和CGLIB动态代理的区别
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理: ● JDK动态代理只提供接口的代理,不支持类的代理Proxy.newProxyInstance(类加载器, 代理对象实现的所有接口, 代理执行器) ● CGLIB是通过继承的方式做的动态代理 , 如果某个类被标记为final,那么它是无法使用 CGLIB做动态代理的。Enhancer.create(父类的字节码对象, 代理执行器)
|
4月前
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类方法的执行。主要通过两种方式实现:JDK动态代理和CGLIB动态代理。JDK动态代理基于接口,利用`java.lang.reflect.Proxy`类和`InvocationHandler`接口;CGLIB则通过字节码技术生成目标类的子类作为代理,适用于未实现接口的类。两者均用于在方法执行前后添加额外逻辑,如日志记录、权限控制等,广泛应用于AOP框架中。
108 2
|
5月前
|
监控 Java API
JDK动态代理和CGLIB动态代理
Java动态代理允许在运行时创建代理对象,增强或拦截目标类的方法调用,无需修改原代码。它有两种主要实现方式:JDK动态代理和CGLIB动态代理。 - **JDK动态代理**:通过`java.lang.reflect.Proxy`类和`InvocationHandler`接口实现,适用于实现了接口的类。它在方法调用前后插入额外逻辑,如日志记录、权限控制等。 - **CGLIB动态代理**:基于字节码技术,为未实现接口的类生成子类作为代理,重写父类方法以添加增强逻辑。适用于没有接口的类,但要求目标类不能是`final`类或方法。
|
5月前
|
Java API 数据安全/隐私保护
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
134 0
探索Java动态代理的奥秘:JDK vs CGLIB
|
2天前
|
存储 Ubuntu 安全
在Ubuntu 16.04上安装openjdk-6/7/8-jdk的步骤
在整个安装过程中,你可能需要管理员权限,因此你可能要使用 `sudo` 来获取必要的权限。记得做完每一个步骤后,都要检查输出,以确保没有发生错误,并且每项操作都成功完成。如果在安装过程中遇到问题,查看 `/var/log/` 下的日志文件对于问题的解决可能是有帮助的。
42 21
|
7天前
|
IDE Ubuntu Java
在Ubuntu18.04安装兼容JDK 8的Eclipse集成开发环境的指南。
完成以上步骤后,您将在Ubuntu 18.04系统上成功安装并配置了Eclipse IDE,它将与JDK 8兼容,可以开始进行Java开发工作。如果遇到任何问题,请确保每一步骤都正确执行,并检查是否所有路径都与您的具体情况相匹配。
38 11
|
2月前
|
Java 关系型数据库 MySQL
在Linux平台上进行JDK、Tomcat、MySQL的安装并部署后端项目
现在,你可以通过访问http://Your_IP:Tomcat_Port/Your_Project访问你的项目了。如果一切顺利,你将看到那绚烂的胜利之光照耀在你的项目之上!
209 41
|
2月前
|
开发框架 Java 关系型数据库
在Linux系统中安装JDK、Tomcat、MySQL以及部署J2EE后端接口
校验时,浏览器输入:http://[your_server_IP]:8080/myapp。如果你看到你的应用的欢迎页面,恭喜你,一切都已就绪。
295 17
|
3月前
|
Oracle Java 关系型数据库
Tomcat和JDK的详细安装、下载和环境配置指南
以上就是JDK和Tomcat的下载、安装和环境配置的详细步骤。希望这个指南能帮助你顺利完成设置。
213 32
|
2月前
|
关系型数据库 MySQL Java
安装和配置JDK、Tomcat、MySQL环境,以及如何在Linux下更改后端端口。
遵循这些步骤,你可以顺利完成JDK、Tomcat、MySQL环境的安装和配置,并在Linux下更改后端端口。祝你顺利!
179 11

热门文章

最新文章