






















AI 概述
本文对比Java两种动态代理:JDK代理基于接口,靠Proxy与InvocationHandler实现,仅能代理实现接口的类;CGLIB通过字节码生成目标子类,可代理普通类,但不支持final类/方法。附带代码示例、优缺点与适用场景,同时说明Spring AOP会根据目标是否实现接口自动选择对应代理。
目录
文章目录隐藏

JDK 动态代理 是通过 接口 来实现的代理,只有目标类实现了接口,才能被代理。
而 CGLIB 动态代理 则是通过 继承目标类 来生成代理对象,它可以代理没有接口的类。
JDK 动态代理是 Java 原生支持的代理机制,要求目标类必须实现接口。代理对象在运行时通过 Proxy 类创建,并需要一个 InvocationHandler 来处理方法调用。
JDK 动态代理的核心是 InvocationHandler 接口,通过该接口可以拦截所有方法调用,并在目标方法执行前后执行增强逻辑。Proxy.newProxyInstance() 方法用来生成代理类,代理类的所有方法都会被 invoke() 方法拦截。
import java.lang.reflect.*;
interface HelloService {
void sayHello(String name);
}
class HelloServiceImpl implements HelloService {
public void sayHello(String name) {
System.out.println("Hello, " + name);
}
}
class HelloServiceProxy implements InvocationHandler {
private Object target;
public HelloServiceProxy(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;
}
}
public class ProxyExample {
public static void main(String[] args) {
HelloService helloService = new HelloServiceImpl();
HelloService proxy = (HelloService) Proxy.newProxyInstance(
helloService.getClass().getClassLoader(),
helloService.getClass().getInterfaces(),
new HelloServiceProxy(helloService));
proxy.sayHello("World");
}
}
分析:
HelloService 是接口,HelloServiceImpl 是实现类,HelloServiceProxy 是代理类。HelloServiceProxy 实现了 InvocationHandler 接口,重写了 invoke() 方法,在目标方法执行前后进行增强。CGLIB (Code Generation Library) 是一个第三方库,它通过 继承 目标类并重写其方法来生成动态代理。与 JDK 动态代理不同,CGLIB 代理不需要目标类实现接口,因此能够代理普通类。
CGLIB 动态代理的原理是通过 字节码操作,生成目标类的代理子类,并重写目标类的方法来进行增强。这意味着生成的代理类是目标类的一个子类,并且对方法调用进行拦截。
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
class HelloService {
public void sayHello(String name) {
System.out.println("Hello, " + name);
}
}
class HelloServiceProxy implements MethodInterceptor {
private Object target;
public HelloServiceProxy(Object target) {
this.target = target;
}
@Override
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("After method: " + method.getName());
return result;
}
}
public class CglibProxyExample {
public static void main(String[] args) {
HelloService helloService = new HelloService();
HelloServiceProxy helloServiceProxy = new HelloServiceProxy(helloService);
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(HelloService.class);
enhancer.setCallback(helloServiceProxy);
HelloService proxy = (HelloService) enhancer.create();
proxy.sayHello("World");
}
}
分析:
HelloService 是目标类,HelloServiceProxy 是代理类,Enhancer 用来生成代理类。final 类和方法:由于 CGLIB 是基于继承的方式实现代理,因此它无法代理 final 类和 final 方法。| 特性 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
| 代理方式 | 基于接口代理 | 基于类的继承代理 |
| 目标要求 | 目标类必须实现接口 | 目标类无需实现接口 |
| 代理类生成方式 | 使用反射生成代理类 | 通过字节码生成目标类的子类 |
| 性能 | 由于基于反射,性能较差 | 性能较好,因为直接生成子类 |
| 线程安全 | 和 CGLIB 一样,默认非线程安全 | 和 JDK 动态代理一样,默认非线程安全 |
| 限制 | 只能代理实现了接口的类 | 无法代理 final 类和方法 |
@Transactional)通常使用 CGLIB 代理,如果目标类没有实现接口。在 Spring AOP 中,动态代理用于增强业务逻辑。当你使用注解(例如 @Transactional)时,Spring 会根据目标对象的类型选择适合的代理方式:
final 类和方法。通过了解 JDK 动态代理和 CGLIB 动态代理的原理和区别,你能够在实际开发中更加灵活地选择和使用代理技术,提高代码的可维护性和扩展性。
以上关于JDK动态代理与CGLIB动态代理的区别是什么?的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
「点点赞赏,手留余香」
赞 17 赏
给作者打赏,鼓励TA抓紧创作!
微信
支付宝
还没有人赞赏,快来当第一个赞赏的人吧!
声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » JDK动态代理与CGLIB动态代理的区别是什么?
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。