应友友的要求,本章是对于Java的CGLIB动态代理进行一个通俗的解释,希望能够帮助到奋斗的你,一起加油!!!
🌟 通俗理解CGLIB动态代理
想象你有一个玩具机器人(原始类),现在你想给它增加新功能但又不想拆开它改造。CGLIB就像是一个"魔法复制机":
- 复制并增强:它复制你的机器人,在新机器人里加入额外功能(如发光、说话)
- 保持原样:原来的机器人完全没被改动
- 随时调用:当你使用这个"增强版机器人"时,它会先执行新功能,再执行原来的功能
🆚 和JDK动态代理的区别
- JDK代理:需要机器人有"说明书"(接口),按照说明书复制
- CGLIB代理:直接复制机器人本身,不需要说明书
🔧 使用CGLIB的步骤
1. 添加CGLIB依赖(Maven项目)
xml
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
2. 准备一个普通类(没有接口也行)
java
class Cat {
public void eat() {
System.out.println("小猫吃鱼");
}
public final void sleep() { // final方法不能被代理
System.out.println("小猫睡觉");
}
}
3. 创建代理
java
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibDemo {
public static void main(String[] args) {
// 1. 创建增强器
Enhancer enhancer = new Enhancer();
// 2. 设置父类(要代理的类)
enhancer.setSuperclass(Cat.class);
// 3. 设置回调(相当于JDK代理的InvocationHandler)
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("--- 喂食前洗手 ---"); // 前置增强
Object result = proxy.invokeSuper(obj, args); // 调用原方法
System.out.println("--- 清理猫碗 ---"); // 后置增强
return result;
}
});
// 4. 创建代理对象
Cat proxyCat = (Cat) enhancer.create();
// 5. 使用代理对象
proxyCat.eat();
// 输出:
// --- 喂食前洗手 ---
// 小猫吃鱼
// --- 清理猫碗 ---
proxyCat.sleep(); // final方法不会被代理
// 输出:小猫睡觉(没有增强效果)
}
}
⚠️ 注意事项
- 不能代理final方法:就像你不能改造机器人的固定部件
- 目标类要有无参构造方法:复制机器需要原始蓝图
- 性能比JDK代理略高:但创建代理对象较慢
🌰 实际应用场景
- 在Spring AOP中,当目标类没有实现接口时
- 需要对普通类的方法进行监控、日志记录
- 实现方法调用拦截和功能增强
就像给你的原始机器人加上了"自动清洁"、"语音提醒"等功能,而原来的机器人完全不需要修改!