JVM动态代理和JDK动态代理介绍

news/2025/4/2 6:31:16/

目录

主要区别

概念范围

实现方式

使用场景

性能考虑

JDK%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E4%BB%8B%E7%BB%8D-toc" name="tableOfContents" style="margin-left:0px">JDK动态代理介绍

实现步骤

1. 定义接口

2. 实现目标对象

3. 实现InvocationHandler接口

4. 创建代理对象

执行流程

1. 创建代理对象

2. 方法调用拦截

3. 执行额外逻辑

4. 调用目标方法

应用场景

1. 面向切面编程(AOP)

2. 远程过程调用(RPC)

3. 缓存机制

注意事项

1. 性能开销

2. 接口限制

3. 异常处理

JVM动态代理之CGLIB

核心组件

1. Enhancer类

2. MethodInterceptor接口

3. Callback接口及其实现类

实现步骤

2. 设置目标类

3. 设置拦截器

4. 创建代理对象

5. 调用代理对象的方法

注意事项

1. final类和方法

2. 性能开销

3. 依赖库


主要区别

概念范围

  • JVM动态代理:是一个更广泛的概念,指的是在Java虚拟机(JVM)层面上实现的动态代理技术。它包括了所有在JVM上实现的动态代理技术,不仅限于JDK提供的实现方式。JVM动态代理提供了一种灵活且强大的方式来扩展和修改类的行为,而无需修改原始类的代码。

  • JDK动态代理:是JVM动态代理的一种具体实现方式,基于Java的反射机制。它允许在运行时动态地创建代理类和代理对象,用于替代原始对象进行方法调用,并可以在方法调用前后添加额外的逻辑。JDK动态代理是Java标准库提供的一种动态代理机制。

实现方式

  • JVM动态代理:可以通过多种方式实现,包括但不限于JDK自带的Proxy类、第三方库如CGLIB和ASM等。这些实现方式可能在性能、功能或使用场景上有所不同。

  • JDK动态代理:具体实现依赖于Java的反射机制。它要求被代理的对象必须实现至少一个接口,代理类通过实现与被代理对象相同的接口来拦截方法调用。JDK动态代理的核心类是java.lang.reflect.Proxy,它提供了创建代理类和代理对象的静态方法。

使用场景

  • JVM动态代理:由于涵盖了多种实现方式,因此适用于更广泛的场景。例如,当需要代理没有实现接口的类时,可以使用CGLIB等基于字节码技术的动态代理实现。

  • JDK动态代理:主要适用于代理实现了接口的类。它广泛用于面向切面编程(AOP)、日志记录、事务管理、权限控制等场景。通过JDK动态代理,可以在不修改原始代码的情况下,为方法调用添加额外的逻辑。

性能考虑

  • JVM动态代理:性能可能因实现方式而异。例如,基于反射的JDK动态代理在性能上可能不如基于字节码技术的CGLIB动态代理。

  • JDK动态代理:由于基于反射机制,性能相对较低。但在Java 8及以后的版本中,反射机制的性能得到了优化,使得JDK动态代理的性能有所提升。尽管如此,在性能敏感的场景中,仍然需要考虑使用其他更高效的动态代理实现方式。

JDK%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E4%BB%8B%E7%BB%8D" name="JDK%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E4%BB%8B%E7%BB%8D">JDK动态代理介绍

核心思想是创建一个代理对象,该对象在运行时动态生成,并实现了与目标对象相同的接口。当客户端代码调用代理对象的方法时,动态代理机制会将方法调用转发到目标对象,并在调用前后执行指定的逻辑。

实现步骤

1. 定义接口

首先,需要定义一个或多个接口,目标对象(被代理的对象)必须实现这些接口。代理对象将实现这些接口,以便能够代理目标对象的方法调用。

java">public interface MyInterface {void myMethod();
}

2. 实现目标对象

实现一个类,使其实现前面定义的接口。这个类就是需要被代理的目标对象。

java">public class MyTarget implements MyInterface {@Overridepublic void myMethod() {System.out.println("Executing myMethod in MyTarget");}
}

3. 实现InvocationHandler接口

创建一个处理器类,实现java.lang.reflect.InvocationHandler接口。这个接口包含一个invoke方法,用于处理对代理对象方法的调用。

java">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 call");Object result = method.invoke(target, args); // 调用目标对象的方法System.out.println("After method call");return result;}
}

4. 创建代理对象

使用java.lang.reflect.Proxy类的newProxyInstance方法,根据指定的类加载器、接口数组和InvocationHandler实例,动态生成代理类对象。

java">import java.lang.reflect.Proxy;public class DynamicProxyDemo {public static void main(String[] args) {MyTarget target = new MyTarget(); // 目标对象MyInvocationHandler handler = new MyInvocationHandler(target); // 处理器对象// 动态生成代理对象MyInterface proxy = (MyInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),handler);// 通过代理对象调用目标对象的方法proxy.myMethod();}
}

执行流程

1. 创建代理对象

在运行时,通过Proxy.newProxyInstance方法,JVM根据指定的类加载器、接口数组和InvocationHandler实例,动态生成代理类对象。

2. 方法调用拦截

当客户端代码调用代理对象的方法时,JVM会拦截这次调用,并将调用转发到InvocationHandler对象的invoke方法。

3. 执行额外逻辑

invoke方法中,可以执行额外的逻辑,例如日志记录、安全检查、事务管理等。

4. 调用目标方法

invoke方法中,通过反射机制调用目标对象的方法,并将调用结果返回给客户端代码。

应用场景

1. 面向切面编程(AOP)

在Spring框架中,AOP通过动态代理实现横切关注点的织入,如事务管理、日志记录等。

2. 远程过程调用(RPC)

在RPC框架中,动态代理用于生成远程服务的代理对象,客户端通过调用代理对象的方法,实现对远程服务的调用。

3. 缓存机制

通过动态代理,可以在方法调用前后添加缓存逻辑,提高应用的性能。

注意事项

1. 性能开销

动态代理通过反射机制实现方法调用,相对于直接调用目标对象的方法,存在一定的性能开销。

2. 接口限制

JDK动态代理是基于接口的,因此只能代理实现了接口的类。如果需要代理没有实现接口的类,可以考虑使用CGLIB等第三方库。

3. 异常处理

invoke方法中,需要妥善处理可能抛出的异常,避免影响代理对象的正常使用。

JVM动态代理之CGLIB

CGLIB(Code Generation Library)是一个强大的高性能代码生成库,主要用于在运行时动态生成类和代理对象。CGLIB动态代理通过生成目标类的子类,并在子类中重写目标类的方法来实现对方法调用的拦截。

核心组件

1. Enhancer类

Enhancer类是CGLIB中用于创建代理对象的核心类。它类似于一个工厂,负责生产代理对象。通过设置Enhancer的一些属性,可以指定目标对象、拦截器等信息,然后调用其create()方法来创建代理对象。

2. MethodInterceptor接口

MethodInterceptor接口定义了拦截器的方法。拦截器是CGLIB动态代理的关键部分,用于在目标方法执行前后或异常处理时添加额外的逻辑。实现了该接口的类需要实现intercept()方法,在这个方法中编写增强代码。

3. Callback接口及其实现类

Callback接口是一个更通用的回调接口,MethodInterceptor是它的一个子接口。除了MethodInterceptor,CGLIB还提供了其他一些Callback实现类,用于不同的目的,比如用于处理方法调用结果的FixedValue等。可以将多个Callback实现类组合起来使用,以实现更复杂的代理逻辑。

实现步骤

1. 创建Enhancer对象

首先,需要创建一个Enhancer对象。这个对象将用于生成代理类。

2. 设置目标类

通过调用Enhancer的setSuperclass()方法,设置目标类的超类。这意味着生成的代理类将继承目标类。

3. 设置拦截器

通过调用Enhancer的setCallback()方法,设置一个实现了MethodInterceptor接口的回调对象。该回调对象将负责拦截方法调用并执行额外的逻辑。

4. 创建代理对象

调用Enhancer的create()方法,生成代理类的实例。这个实例就是最终的代理对象。

5. 调用代理对象的方法

当调用代理对象的方法时,该方法调用将被拦截并转发到回调对象的intercept()方法中。在intercept()方法中,可以执行额外的逻辑(如日志记录、权限检查等),然后通过调用MethodProxy.invokeSuper()方法执行目标类的原始方法。

java">import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;class TargetClass {public void method1() {System.out.println("执行目标方法 method1");}public void method2() {System.out.println("执行目标方法 method2");}
}class MyInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("在方法执行前添加的逻辑");Object result = proxy.invokeSuper(obj, args);System.out.println("在方法执行后添加的逻辑");return result;}
}public class CglibProxyTest {public static void main(String[] args) {// 创建 Enhancer 对象Enhancer enhancer = new Enhancer();// 设置目标类enhancer.setSuperclass(TargetClass.class);// 设置拦截器enhancer.setCallback(new MyInterceptor());// 创建代理对象TargetClass proxy = (TargetClass) enhancer.create();// 调用代理对象的方法proxy.method1();proxy.method2();}
}

注意事项

1. final类和方法

由于CGLIB通过继承方式创建代理类,因此目标类不能是final的,否则会导致代理失败。此外,目标类中的final方法也无法被代理,因为final方法不能被重写。

2. 性能开销

CGLIB在生成代理类时需要进行字节码操作,这可能会带来一定的性能开销。因此,在性能敏感的场景中,需要谨慎使用CGLIB动态代理。

3. 依赖库

CGLIB是一个第三方库,使用时需要将其添加到项目的依赖中。通常,可以通过Maven或Gradle等构建工具来管理CGLIB的依赖。


http://www.ppmy.cn/news/1584567.html

相关文章

机器学习day1(英)

What is machine learning? Field of study gives computers the ability to learn without being expilicity programmed. Supervised learning 监督学习Usupervised learning 无监督学习Reinforcement learning 强化学习 Supervised learning definition:learns from be…

Windows 我的世界 Minecraft 服务器搭建,Fabric 模组搭建教程(内网穿透)

Windows 我的世界 Minecraft 服务器搭建,Fabric 模组搭建教程(内网穿透) 一、下载 Fabric 服务端二、本地测试连接三、上传至服务器 / 上传MCSManager四、下载樱花,实现内网穿透,邀请其他玩家一起玩五、MCSManager 面板…

责任链模式_行为型_GOF23

责任链模式 责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,核心思想是将多个处理请求的对象连成一条链,请求沿链传递直到被处理。它像现实中的“多级审批流程”——请假或报销时,申请会逐级提交给…

通过 Docker Swarm 集群探究 Overlay 网络跨主机通信原理

什么是Overlay网络, 用于解决什么问题 ? Overlay网络通过在现有网络之上创建一个虚拟网络层, 解决不同主机的容器之间相互通信的问题 如果没有Overlay网络,实现跨主机的容器通信通常需要以下方法: 端口映射使用宿主机网络模式 这些方法牺牲了容器网络…

Turnitin系统查重,论文会被收录吗?

Turnitin系统目前是可以检测语言范围最广的论文检测系统,还可以检测小语种论文。 Turnitin是世界上主流的学术不端检测系统之一,它的系统与国际著名出版商(收录90%以上的SCI期刊)指定使用的CrossCheck反剽窃检测系统的技术支持、…

项目-苍穹外卖(十三) 地址模块(导入)+用户下单

一、地址模块 需求分析和设计: 新增地址: Controller: /*** 新增地址** param addressBook* return*/PostMappingApiOperation("新增地址")public Result save(RequestBody AddressBook addressBook) {addressBookService.save(addressBook);return Resu…

Playwright从入门到实战:比Selenium更快的数据爬取案例实战

摘要 Playwright 是微软开源的下一代浏览器自动化工具,凭借其高性能、跨浏览器支持和现代化设计,迅速成为 Web 自动化领域的热门选择。本文将从 安装配置 开始,通过 实战演练 展示其核心功能,并与 Selenium 深度对比,…

漏洞挖掘---灵当CRM客户管理系统getOrderList SQL注入漏洞

一、灵当CRM 灵当CRM是上海灵当信息科技有限公司旗下产品,适用于中小型企业。它功能丰富,涵盖销售、服务、财务等管理功能,具有性价比高、简洁易用、可定制、部署灵活等特点,能助力企业提升经营效益和客户满意度。 二、FOFA-Sear…