Java 的动态代理(Dynamic Proxy)是 Java 提供的一种允许在运行时动态创建代理对象的机制,用于拦截和处理对目标对象方法的调用,它基于 Java 的反射机制,被广泛运用于 AOP (面向切面编程)、框架开发(如 Spring)等领域。
区别于静态代理(需要手动编写代理类),动态代理在运行时通过反射动态生成代理类,无需为每个目标类手动编写代理代码。
Java 中的动态代理主要基于 java.lang.reflect.Proxy 和 InvocationHandler 接口。其中 Proxy 类用于动态生成代理对象,InvocationHandler 接口用于定义代理逻辑,每次调用代理对象的方法时,会触发 InvocationHandler 的 invoke 方法。
动态代理要求目标对象必须实现至少一个接口,因为代理对象是通过接口生成的。
下面给出一个简单的动态代理示例:
java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个接口
interface UserService {
void sayHello(String name);
}
// 目标类(被代理的实现类)
class UserServiceImpl implements UserService {
@Override
public void sayHello(String name) {
System.out.println("Hello, " + name + "!");
}
}
// 自定义 InvocationHandler
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 result = method.invoke(target, args); // 调用目标对象的方法
System.out.println("方法调用后:清理资源");
return result;
}
}
// 测试
public class Main {
public static void main(String[] args) {
// 创建目标对象
UserServiceImpl target = new UserServiceImpl();
// 创建 InvocationHandler
MyInvocationHandler handler = new MyInvocationHandler(target);
// 生成代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(), // 类加载器
target.getClass().getInterfaces(), // 目标实现的接口
handler // InvocationHandler
);
// 调用代理对象的方法
proxy.sayHello("Alice");
}
}
输出结果:
java
方法调用前:记录日志
Hello, Alice!
方法调用后:清理资源
Prxoy.newProxyInstance 在运行时生成一个代理类,这个代理类的字节码是动态创建的,通常以 $Proxy0 这样的形式命名,代理类的每个方法都会调用 InvocationHandler.invoke 。
当调用代理对象的方法(如 proxy.sayHello)时,实际执行的是 InvocationHandler.invoke。invoke 方法接收三个参数:proxy 表示代理对象本身,method 表示被调用的方法(反射的 Method 对象),args 表示方法参数。在 invoke 中可以自定义逻辑(如日志、权限检查),然后通过 method.invoke(target, args) 调用目标对象的方法。
动态代理实现了代理逻辑与业务逻辑分离,符合 AOP 思想。同一个 InvocationHandler 可以代理多个接口或对象。
动态代理使用的反射机制有一定的性能开销。