java动态代理
动态代理是指在程序运行过程中动态地创建代理类和对象的技术。通过动态代理,我们可以在不修改源代码的情况下,在方法执行前后加入一些附加操作,比如日志记录、性能统计、事务管理等。
在 Java 中,动态代理主要有两种实现方式:
1. 基于接口的动态代理(JDK 动态代理):使用 java.lang.reflect.Proxy
类和 java.lang.reflect.InvocationHandler
接口来创建代理对象。被代理的类必须实现一个或多个接口。
2. 基于继承的动态代理(CGLIB 动态代理):使用 CGLIB 库来创建代理对象,无需被代理的类实现接口。
动态代理常用于 AOP(面向切面编程)等方面,它可以帮助我们将与核心业务逻辑相关的横切关注点(如日志记录、事务管理等)与业务逻辑本身分离。这样可以提高代码的模块化程度,使得代码更易于维护和升级。
动态代理是一种在运行时动态生成代理对象的技术,它允许在不修改原始类的情况下,通过代理对象来间接访问原始类的方法。动态代理常用于 AOP(面向切面编程)和基于接口的代理。
基于接口的动态代理(JDK 动态代理)
1. 基于接口的动态代理(JDK 动态代理):基于 Java 的反射机制,利用 java.lang.reflect.Proxy
类和 java.lang.reflect.InvocationHandler
接口来实现动态代理。JDK 动态代理要求被代理的类必须实现一个或多个接口。
下面是一个简单的示例代码,演示如何使用 JDK 动态代理:
interface Calculator {
int add(int a, int b);
}
class CalculatorImpl implements Calculator {
public int add(int a, int b) {
return a + b;
}
}
class LoggingInvocationHandler implements InvocationHandler {
private Object target;
public LoggingInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoking method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After invoking method: " + method.getName());
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
Calculator calculator = new CalculatorImpl();
Calculator proxy = (Calculator) Proxy.newProxyInstance(
calculator.getClass().getClassLoader(),
calculator.getClass().getInterfaces(),
new LoggingInvocationHandler(calculator));
int result = proxy.add(2, 3); // 这里实际上会调用 LoggingInvocationHandler 中的 invoke 方法
System.out.println("Result: " + result);
}
}
CGLIB
CGLIB(Code Generation Library)是一个强大的基于字节码的代码生成库,它可以在运行时动态地生成新的 class。CGLIB 动态代理是指使用 CGLIB 库来生成代理类,并通过代理类来实现对目标类的代理。
与基于接口的动态代理不同,CGLIB 动态代理可以代理没有实现任何接口的类。它通过生成目标类的子类,并在子类中对目标类的方法进行拦截和增强实现代理功能。
在 CGLIB 动态代理中,代理类的生成过程主要包括以下几个步骤:
1. 创建 Enhancer 对象:使用 CGLIB 提供的 Enhancer 类创建一个代理类生成器对象。
2. 设置目标类(被代理类):将目标类设置为 Enhancer 对象的父类,以便生成的代理类成为目标类的子类。
3. 设置回调函数(Interceptor):使用 Enhancer 对象的 setCallback 方法设置方法拦截器,也就是在代理对象调用方法时的增强逻辑。
4. 创建代理对象:通过 Enhancer 对象的 create 方法创建代理对象,并将代理对象强制转换为目标类类型。
CGLIB 动态代理的实现原理相对复杂,但它具有很强的灵活性和扩展性,可以代理没有实现接口的类,从而能够对更多类型的类进行代理。它在 Spring 等框架中被广泛应用,用于实现 AOP 功能、对目标类进行增强等方面。
使用 CGLIB 动态代理需要引入 CGLIB 库,并按照以下步骤进行操作:
1. 引入 CGLIB 库:在 Maven 项目中,在 pom.xml
文件中加入以下依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
或者在 Gradle 项目中,在 build.gradle
文件中加入以下依赖:
dependencies {
implementation 'cglib:cglib:3.3.0' // 替换为最新版本
}
2. 创建目标类:创建一个普通的 Java 类作为被代理的目标类。
3. 创建拦截器(Interceptor)类:编写一个类来实现对目标类方法的拦截和增强逻辑。
4. 使用 Enhancer 生成代理对象:使用 CGLIB 的 Enhancer 类来生成代理类,并创建代理对象。
下面是一个简单的示例,演示了如何使用 CGLIB 动态代理:
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 doSomething() {
System.out.println("TargetClass: Doing something...");
}
}
// 拦截器类
class MyInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method " + method.getName());
Object result = proxy.invokeSuper(obj, args); // 调用目标类的方法
System.out.println("After method " + method.getName());
return result;
}
}
public class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetClass.class);
enhancer.setCallback(new MyInterceptor());
TargetClass proxy = (TargetClass) enhancer.create();
proxy.doSomething(); // 调用代理对象的方法
}
}
转载自:https://juejin.cn/post/7304566897411915791