Java中的动态代理是指在运行时动态生成代理类来增强目标对象功能的一种机制。JDK自带的动态代理基于反射包中的Proxy类和InvocationHandler接口实现,不需要额外依赖第三方库,适合处理接口层面的方法拦截。

为什么需要动态代理
在业务开发中,我们经常需要在方法执行前后添加日志、鉴权或事务控制。如果为每个类都写一个代理类,代码会非常冗余,这被称为静态代理的缺点。JDK动态代理可以在运行时为接口自动生成代理对象,把通用逻辑集中在InvocationHandler里。
InvocationHandler接口核心方法
InvocationHandler只有一个方法:
public interface InvocationHandler {
// proxy 是代理对象,method 是被调用的方法,args 是方法参数
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
完整实战示例
下面以用户服务接口为例,演示如何使用JDK动态代理记录方法耗时。
1. 定义业务接口
public interface UserService {
void save(String name);
String find(int id);
}
2. 实现真实类
public class UserServiceImpl implements UserService {
@Override
public void save(String name) {
System.out.println("保存用户: " + name);
}
@Override
public String find(int id) {
return "用户" + id;
}
}
3. 编写InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LogHandler implements InvocationHandler {
private Object target;
public LogHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("调用前: " + method.getName());
Object result = method.invoke(target, args);
long end = System.currentTimeMillis();
System.out.println("调用后: " + method.getName() + " 耗时 " + (end - start) + "ms");
return result;
}
}
4. 创建并使用代理对象
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
UserService real = new UserServiceImpl();
LogHandler handler = new LogHandler(real);
UserService proxy = (UserService) Proxy.newProxyInstance(
real.getClass().getClassLoader(),
real.getClass().getInterfaces(),
handler
);
proxy.save("张三");
System.out.println(proxy.find(1));
}
}
使用注意事项
- JDK动态代理只能代理接口,不能代理普通类,若需代理类可使用CGLIB。
- 在invoke方法内部要避免通过proxy对象自调用,否则会陷入递归。
- method.invoke(target, args)中的target应是真实对象而非proxy。
小结
通过上述步骤,我们基于InvocationHandler和Proxy实现了一个简单的Java动态代理。实际框架如Spring AOP在默认情况下也是利用JDK动态代理来处理接口 Bean 的增强逻辑,理解它有助于排查代理失效等问题。
Java动态代理InvocationHandlerJDK代理修改时间:2026-07-29 14:39:23