JDK 动态代理 和 CGLIB 动态代理
·
JDK 动态代理 和 CGLIB 动态代理 都是 Java 中实现 AOP(面向切面编程) 的常见方式,例如 Spring AOP 就使用这两种代理。
核心区别在于:代理对象生成方式不同。
一、JDK 动态代理
JDK 动态代理是基于接口实现的代理。
它会在运行时 生成一个实现目标接口的代理类,然后在方法调用时进行拦截。
实现原理
JDK使用:
- java.lang.reflect.Proxy
- InvocationHandler
代理流程:
接口 ↓ 目标对象实现接口 ↓ Proxy生成代理对象 ↓ InvocationHandler拦截方法
示例代码
interface UserService {
void login();
}
class UserServiceImpl implements UserService {
public void login() {
System.out.println("登录方法");
}
}
代理实现:
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxyObj, method, args) -> {
System.out.println("方法执行前");
Object result = method.invoke(target, args);
System.out.println("方法执行后");
return result;
}
);
特点
- 必须有接口
- 基于 反射机制
- JDK自带,不需要第三方库
二、CGLIB 动态代理
CGLIB 是基于继承实现代理。
它会 生成目标类的子类,通过重写方法实现增强。
使用技术:
- ASM字节码技术
代理流程:
目标类 ↓ CGLIB生成子类 ↓ 重写方法 ↓ MethodInterceptor拦截
示例代码
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
System.out.println("方法执行前");
Object result = proxy.invokeSuper(obj, args);
System.out.println("方法执行后");
return result;
});
UserServiceImpl proxy = (UserServiceImpl) enhancer.create();
三、核心区别
| 对比 | JDK动态代理 | CGLIB |
|---|---|---|
| 实现方式 | 基于接口 | 基于继承 |
| 是否需要接口 | 必须需要 | 不需要 |
| 生成类方式 | 实现接口 | 生成子类 |
| 技术 | 反射 | ASM字节码 |
| final类 | 可以 | 不可以 |
| final方法 | 可以 | 不能代理 |
四、Spring AOP 如何选择
Spring默认策略:
- 如果有接口 → 使用 JDK 动态代理
- 如果没有接口 → 使用 CGLIB
Spring Boot 2 之后 默认使用 CGLIB。
也可以手动配置:
spring.aop.proxy-target-class=true
表示 强制使用 CGLIB。
五、面试一句话总结
可以这样回答:
JDK 动态代理是基于接口实现的,通过 Proxy 和 InvocationHandler 在运行时生成代理类;而 CGLIB 是基于继承实现的,通过生成目标类的子类并重写方法进行增强。Spring AOP 默认优先使用 JDK 动态代理,如果没有接口则使用 CGLIB。
更多推荐





所有评论(0)