Java 动态代理核心原理与 JDK/CGLIB 实战对比
在 Java 开发中,代理模式是设计模式的经典应用,而动态代理更是框架开发的基石。无论是 Spring AOP 的事务管理,还是日志记录、权限校验,背后都离不开它。今天我们就抛开那些晦涩的理论,直接拆解两种主流动态代理的实现逻辑,看看在实际项目中该如何选型。
动态代理的核心概念
动态代理的本质是在程序运行时,通过反射机制动态生成代理类,而不是在编译期就写好。这样做的好处很明显:你不需要为每个目标类手动编写一个对应的代理类,就能统一给一堆类添加相同的横切逻辑(比如日志、事务),代码耦合度瞬间降低。
这里涉及三个核心角色:
- 目标类(Target):被代理的原始类,装着核心业务逻辑。
- 代理类(Proxy):运行时动态生成的类,持有目标类引用,负责调用目标方法并增强逻辑。
- 增强逻辑(Advice):需要统一添加的横切逻辑,比如打印日志、参数校验等。
形象点说,就像你去银行办事,柜台就是目标类,大堂经理就是代理类,他帮你填表、引导流程,最后才把单子交给柜台处理。
JDK 动态代理:原生 API 的便捷性
JDK 动态代理依赖 java.lang.reflect 包下的 Proxy 和 InvocationHandler 接口。它的硬性要求是:目标类必须实现至少一个接口。
运行时,JVM 会动态生成一个实现了目标接口的代理类。当你调用代理对象的方法时,实际会转发到 InvocationHandler 的 invoke 方法里。你可以在这里嵌入增强逻辑,然后决定是否调用目标方法。
代码实战
// 1. 定义接口
public interface UserService {
void addUser(String name);
}
// 2. 实现目标类
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
}
// 3. 实现 InvocationHandler(增强逻辑)
public class LogInvocationHandler implements InvocationHandler {
private Object target; // 目标类引用
{
.target = target;
}
Object Throwable {
System.out.println( + method.getName() + + Arrays.toString(args));
method.invoke(target, args);
System.out.println( + method.getName() + );
result;
}
}
{
{
();
(UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(target)
);
proxy.addUser();
}
}


