动态代理是一种在运行时创建代理类和对象的技术,允许在不修改原始类代码的情况下,向其添加额外的功能。在 Java 中,主要有两种方式来实现动态代理:JDK 动态代理和 CGLIB(Code Generation Library)代理。
JDK 动态代理:
JDK 动态代理是 Java 提供的一种在运行时创建代理类和对象的方式。它基于接口(Interface)的代理,利用 Java 的反射机制来创建代理对象。主要涉及的类有 java.lang.reflect.Proxy
和 java.lang.reflect.InvocationHandler
。
如何使用 JDK 动态代理:
-
定义接口: 首先需要定义一个接口,以确定代理类的行为。
-
实现 InvocationHandler 接口: 创建一个类来实现
InvocationHandler
接口,重写invoke
方法,在该方法中添加代理类的具体行为。 -
使用 Proxy 创建代理对象: 利用
Proxy.newProxyInstance()
方法创建代理对象,并传入接口类加载器、接口数组、以及实现了InvocationHandler
接口的类的实例。该方法会返回一个实现了指定接口的代理对象。
CGLIB 代理:
CGLIB 是一个强大的、高性能的代码生成类库,它可以在运行时动态生成指定类的子类。相对于 JDK 动态代理,CGLIB 代理不要求目标对象实现接口,因此可以代理没有实现接口的类。CGLIB 库通过扩展目标类创建其子类,并在子类中拦截方法调用实现代理功能。
如何使用 CGLIB 代理:
-
引入 CGLIB 库: 首先需要引入 CGLIB 库的依赖。
-
创建 Enhancer 对象: 使用 CGLIB 的
Enhancer
类创建一个代理类,设置父类和回调(Callback)。 -
设置 Callback: 创建一个实现
MethodInterceptor
接口的类,重写intercept
方法,在该方法中添加代理类的具体行为。 -
生成代理对象: 调用
Enhancer
对象的create()
方法生成代理对象。
JDK 动态代理 vs. CGLIB 代理:
-
JDK 动态代理:
- 基于接口的代理。
- 代理类必须实现一个或多个接口。
- 使用 Java 标准库提供的反射机制。
- 创建速度较慢,但执行效率相对较高。
-
CGLIB 代理:
- 基于继承的代理。
- 可以代理未实现接口的类。
- 使用字节码技术生成目标类的子类。
- 创建速度较快,但执行效率稍低。
一般情况下,如果目标类实现了接口,推荐使用 JDK 动态代理;如果目标类没有实现接口或者需要对类的方法进行代理,可以选择使用 CGLIB 代理。