CGLIB动态代理
本文最后更新于 2025-11-20,文章内容可能已经过时。
CGLIB确实是处理"没有实现接口的类"动态代理的绝佳选择,详细讲讲它的使用方法和适用场景。
什么是CGLIB?
CGLIB(Code Generation Library)是一个强大的高性能代码生成库,它通过在运行时动态生成字节码,为Java类创建代理对象。与JDK动态代理不同,CGLIB不需要被代理类实现接口,它通过创建目标类的子类来实现代理,特别适合处理没有接口的普通类。
CGLIB的核心特点
| 特点 | 说明 |
|---|---|
| 字节码生成 | 在运行时动态生成新类或方法 |
| 子类化 | 通过创建目标类的子类实现代理 |
| 高性能 | 相比JDK动态代理的反射机制,执行速度更快 |
| 无接口依赖 | 无需被代理类实现任何接口 |
| 代理范围广 | 可以代理类中的所有方法(但不能代理final方法) |
CGLIB的使用步骤
1. 添加依赖(Maven项目)
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
2. 定义目标类
public class UserService {
public void addUser(String username) {
System.out.println("User " + username + " added.");
}
public void deleteUser(String username) {
System.out.println("User " + username + " deleted.");
}
}
3. 实现MethodInterceptor接口(创建拦截器)
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 方法调用前的逻辑
System.out.println("Before method: " + method.getName());
// 调用原始方法
Object result = proxy.invokeSuper(obj, args);
// 方法调用后的逻辑
System.out.println("After method: " + method.getName());
return result;
}
}
4. 创建代理对象
import net.sf.cglib.proxy.Enhancer;
public class CglibDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new CglibInterceptor());
UserService userService = (UserService) enhancer.create();
userService.addUser("Alice");
}
}
运行结果:
Before method: addUser
User Alice added.
After method: addUser
CGLIB的使用场景详解
1. 被代理类没有实现接口
这是CGLIB最典型的应用场景。当你的类没有实现任何接口,但你又想为它添加额外功能(如日志、事务管理等)时,CGLIB是唯一选择。
// 没有实现任何接口的类
public class OrderService {
public void placeOrder() {
System.out.println("Order placed");
}
}
// 使用CGLIB为OrderService添加日志功能
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OrderService.class);
enhancer.setCallback(new LoggingInterceptor());
OrderService orderService = (OrderService) enhancer.create();
orderService.placeOrder(); // 会输出日志
2. 高性能要求的场景
CGLIB通过生成子类并调用父类方法,避免了JDK动态代理的反射开销,性能更好。在需要处理大量请求的系统中,CGLIB的性能优势会更明显。
3. AOP(面向切面编程)实现
Spring AOP在需要代理具体类(而非接口)时,会自动使用CGLIB。例如:
- 为没有接口的类添加事务管理
- 为没有接口的类添加日志记录
- 为没有接口的类添加缓存功能
4. 代理final类或final方法
- JDK动态代理:
- 可以代理final方法
- 可以代理实现了接口的final类(因为代理的是接口,不是类本身)
- 不能代理没有实现接口的类
- CGLIB动态代理:
- 不能代理final方法
- 不能代理final类
- 可以代理非final类(无论是否实现了接口)
CGLIB vs JDK动态代理
| 特点 | JDK动态代理 | CGLIB动态代理 |
|---|---|---|
| 代理原理 | 基于接口 | 基于字节码生成(子类化) |
| 被代理类要求 | 必须实现接口 | 无需实现接口 |
| 性能 | 较低(使用反射) | 较高(直接调用) |
| 适用场景 | 有接口的类 | 无接口的类 |
| 代理方法 | 仅代理接口中的方法 | 代理类中所有方法 |
| 侵入性 | 需要被代理类实现接口 | 无需修改被代理类 |
使用CGLIB的注意事项
- 不能代理final类:CGLIB通过继承实现代理,final类无法被继承。
- 不能代理final方法:CGLIB无法重写final方法。
- 性能考虑:虽然CGLIB性能优于JDK,但生成代理类仍有一定开销,频繁创建代理对象时需注意。
- 封装性:由于CGLIB是通过继承实现,可能会破坏被代理类的封装性。
实际应用案例
在Spring框架中,CGLIB常用于以下场景:
- 当一个类没有实现接口,但需要AOP功能时
- 当需要为一个类添加事务管理,但该类没有实现接口时
// Spring中配置CGLIB代理
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // 使用CGLIB代理
public class AppConfig {
// 配置AOP
}
总结
CGLIB是处理"没有实现接口的类"动态代理的绝佳工具,特别适合:
- 为普通类(无接口)添加功能
- 需要高性能的代理场景
- AOP实现中需要代理具体类的情况
它的核心优势在于无需接口,通过字节码生成实现代理,性能优于JDK动态代理。不过使用时要注意final类和final方法的限制。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 软件从业者Hort
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

