深入解析JDK动态代理机制与实现
需积分: 37 187 浏览量
更新于2024-09-07
1
收藏 18KB MD 举报
本文主要分析了Java中的JDK动态代理机制,对比了静态代理与动态代理的区别,并深入探讨了动态代理的底层实现。通过反编译生成的class文件,我们可以更深入地理解JDK动态代理的工作原理。同时,文中也提到了JDK动态代理与CGLIB库的区别。
在Java中,动态代理是一种在运行时创建代理对象的技术,它允许我们为已存在的接口动态地生成代理类。与静态代理相比,动态代理更灵活,因为无需为每个被代理类手动创建代理类。静态代理通常需要为每个接口实现一个代理类,而动态代理则可以通过InvocationHandler接口在运行时生成代理实例。
首先,我们来看一个简单的例子。`IUserService`是我们的业务接口,`UserServiceImpl`是其具体实现。动态代理的核心在于`InvocationHandler`接口的实现,这里我们创建了一个名为`MyInvocationHandler`的类,它会处理代理对象的方法调用。
```java
public interface IUserService {
void add(String name);
}
public class UserServiceImpl implements IUserService {
@Override
public void add(String name) {
System.out.println("向数据库中插入名为:" + name + "的用户");
}
}
public 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("准备向数据库中插入数据");
Object returnValue = method.invoke(target, args);
System.out.println("插入数据库成功");
return returnValue;
}
}
```
在`DynamicProxyTest`类中,我们创建了一个`IUserService`接口的代理对象,通过`Proxy.newProxyInstance()`方法来实现:
```java
public class DynamicProxyTest {
public static void main(String[] args) {
IUserService target = new UserServiceImpl();
MyInvocationHandler handler = new MyInvocationHandler(target);
// 第一个参数是代理类的类加载器,这里使用测试类的类加载器
// 第二个参数是代理类需要实现的接口,即IUserService接口
// 第三个参数是InvocationHandler,这里传入我们实现的handler
IUserService proxyObject = (IUserService) Proxy.newProxyInstance(
DynamicProxyTest.class.getClassLoader(),
new Class[]{IUserService.class},
handler
);
proxyObject.add("张三");
}
}
```
当调用`proxyObject.add("张三")`时,实际上会由`MyInvocationHandler`的`invoke()`方法处理。`invoke()`方法首先执行预处理操作(如打印日志),然后调用实际目标对象的方法,最后进行后处理(如确认操作成功)。
JDK动态代理的底层实现依赖于Java的反射机制。`Proxy.newProxyInstance()`方法会根据传递的接口列表生成一个新的类,这个类实现了所有给定的接口,并且继承了`java.lang.reflect.Proxy`类。这个生成的代理类会在运行时动态地被类加载器加载。每次调用代理对象的方法时,实际上是调用了`Proxy`类的`invoke()`方法,然后转发到我们自定义的`InvocationHandler`。
JDK动态代理与CGLIB的区别在于,JDK动态代理只能为实现了接口的类生成代理,而CGLIB则是通过字节码技术为没有实现接口的类生成代理。如果目标类没有实现接口,那么就需要使用CGLIB库来创建代理。CGLIB代理在性能上可能优于JDK动态代理,因为它不需要通过接口调用,而是直接通过子类化实现。然而,由于JDK动态代理的代码更简洁,且无需引入额外的库,所以在许多场景下仍然是首选。
JDK动态代理提供了一种方便的方式,让我们可以在不修改原有代码的情况下,对方法调用添加额外的行为,比如事务管理、日志记录等。这种设计模式在AOP(面向切面编程)中得到了广泛应用。
200 浏览量
点击了解资源详情
871 浏览量
2055 浏览量
点击了解资源详情
149 浏览量
948 浏览量
2024-03-23 上传
1202 浏览量
qq_39609292
- 粉丝: 0
- 资源: 2
最新资源
- cesium js 指北针
- PRIMA-CRM客户关系管理系统源代码
- 数据_扇形FBP_ct数据_扇形CT_giftcja_FBP
- phylopeachtree.github.io:Peachtree-在树上绘制流行病学和对齐字符
- 开课吧 vue面试题训练营
- 易语言超级列表框排序源码,易语言超级列表框排序_增加时间排序源
- Dark Patterns-crx插件
- boxy:使用Phaser 3的演示平台游戏
- staffdashboard
- Textarea Lift-off-crx插件
- TSSOS:基于矩SOS层次结构的稀疏多项式优化工具
- audio-flac:audioflac 包
- wAppbar:Windows桌面应用程序栏(appbar),基于Nim和wNim Framework
- MCQTabbedAppPOC
- Color-Identifying-Game:通过查看红色,绿色和蓝色值来识别颜色
- 易语言超级列表框指定行着色