深入解析CGLIB:动态代理的强大利器

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

CGLIB(Code Generation Library)是一个强大的字节码生成库,它在运行时动态生成被代理类的子类,通过继承的方式实现代理。由于不需要接口,CGLIB 可以代理普通类,弥补了 JDK 动态代理必须基于接口的局限性。


核心特性

  1. 无需接口:通过继承目标类生成代理子类。
  2. 方法拦截:通过 MethodInterceptor 接口实现方法增强。
  3. 性能优化:使用 FastClass 机制避免反射调用,提升性能。

实现原理

  1. 继承目标类:生成目标类的子类,重写非 final 方法。
  2. 方法拦截:在子类中调用 MethodInterceptor.intercept() 实现对方法的增强。
  3. 字节码操作:基于 ASM 框架直接操作字节码生成代理类。

代码示例

1. 添加依赖
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>
2. 目标类(无需接口)
public class UserService {
    public void addUser(String name) {
        System.out.println("添加用户: " + name);
    }

    public final void finalMethod() {
        System.out.println("Final 方法,无法被代理");
    }
}
3. 方法拦截器
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class UserServiceInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("[CGLIB] 前置处理: " + method.getName());
        Object result = proxy.invokeSuper(obj, args); // 调用父类(目标类)方法
        System.out.println("[CGLIB] 后置处理");
        return result;
    }
}
4. 生成代理对象
import net.sf.cglib.proxy.Enhancer;

public class CglibDemo {
    public static void main(String[] args) {
        // 1. 创建 Enhancer 实例
        Enhancer enhancer = new Enhancer();
        // 2. 设置父类(目标类)
        enhancer.setSuperclass(UserService.class);
        // 3. 设置回调(方法拦截器)
        enhancer.setCallback(new UserServiceInterceptor());

        // 4. 创建代理对象
        UserService proxy = (UserService) enhancer.create();

        // 5. 调用代理方法
        proxy.addUser("Alice");
        // 输出:
        // [CGLIB] 前置处理: addUser
        // 添加用户: Alice
        // [CGLIB] 后置处理

        proxy.finalMethod(); // 直接调用父类 final 方法,无增强
        // 输出: Final 方法,无法被代理
    }
}

CGLIB 关键组件

  1. Enhancer:用于生成代理类的核心类,设置父类和方法拦截器。
  2. MethodInterceptor:方法拦截器接口,实现横切逻辑。
  3. CallbackFilter:根据方法选择不同的回调策略。

局限性

  1. 无法代理 final 类/方法:因为 CGLIB 通过继承实现。
  2. 构造方法调用自身方法时无法增强:由于目标类内部调用不会经过代理类。
    public class UserService {
        public void methodA() {
            methodB(); // 直接调用,不会被拦截
        }
        public void methodB() { ... }
    }
    

CGLIB vs JDK 动态代理

特性CGLIBJDK 动态代理
代理方式继承接口实现
目标类要求非 final 类/方法必须实现接口
性能通常更快(FastClass 优化)反射调用稍慢
依赖ASM 字节库Java 原生 API

Spring 中的选择

  • 若目标类实现了接口,默认使用 JDK 动态代理
  • 若目标类未实现接口,使用 CGLIB
  • 可通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 强制使用 CGLIB。

总结

CGLIB 通过动态生成子类实现代理,适用于无接口的普通类,提供了灵活的方法拦截机制。尽管有 final 方法的限制,但其高性能和广泛的应用场景(如 Spring AOP、Hibernate)使其成为 Java 生态中不可或缺的工具。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值