在 Java 中,动态代理是一种强大的机制,允许程序在运行时创建一个实现了一组指定接口的代理对象。这种机制主要用于在不修改原始类的情况下,为方法调用添加额外的行为,比如日志记录、事务管理等。Java 提供了两种主要的方式来进行动态代理:JDK 动态代理和 CGLIB 动态代理。
JDK 动态代理
- 基本概念:JDK 动态代理是 Java 原生支持的一种代理方式,它主要通过
java.lang.reflect.Proxy
类来创建代理对象,并使用InvocationHandler
接口来处理代理对象的方法调用。 - 适用范围:仅适用于实现了接口的类。也就是说,目标类必须至少实现一个接口,JDK 动态代理会为这些接口生成代理对象。
- 工作原理:
- 首先定义一个或多个接口。
- 然后创建一个实现了
InvocationHandler
接口的处理器类,这个处理器负责实现代理逻辑。 - 使用
Proxy.newProxyInstance()
方法创建代理对象,该方法需要类加载器、目标接口数组以及InvocationHandler
实例作为参数。 - 当调用代理对象上的方法时,实际上会调用
InvocationHandler
的invoke()
方法,在这里可以执行自定义逻辑(如前置处理、后置处理)并调用目标对象的实际方法。
示例代码
// 定义一个接口
public interface Service {
void doSomething();
}
// 实现该接口的目标类
public class ServiceImpl implements Service {
public void doSomething() {
System.out.println("Doing something...");
}
}
// 创建 InvocationHandler 的实现
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
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("Before method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return result;
}
}
// 使用 Proxy 创建代理对象
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
Service target = new ServiceImpl();
MyInvocationHandler handler = new MyInvocationHandler(target);
Service proxy = (Service) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler);
proxy.doSomething();
}
}
CGLIB 动态代理
虽然 JDK 动态代理功能强大,但它只能代理实现了接口的类。对于没有实现任何接口的类,可以使用 CGLIB(Code Generation Library)。CGLIB 是一个第三方库,通过继承的方式实现代理对象,它可以为未实现接口的类创建代理。
总的来说,Java 中的动态代理提供了一种灵活且强大的机制,可以在不改变原有代码的基础上增强或控制对对象的方法调用。根据具体需求选择合适的动态代理方式能够帮助开发者更高效地解决问题。
THE END