本文最后更新于 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的注意事项

  1. 不能代理final类:CGLIB通过继承实现代理,final类无法被继承。
  2. 不能代理final方法:CGLIB无法重写final方法。
  3. 性能考虑:虽然CGLIB性能优于JDK,但生成代理类仍有一定开销,频繁创建代理对象时需注意。
  4. 封装性:由于CGLIB是通过继承实现,可能会破坏被代理类的封装性。

实际应用案例

在Spring框架中,CGLIB常用于以下场景:

  • 当一个类没有实现接口,但需要AOP功能时
  • 当需要为一个类添加事务管理,但该类没有实现接口时
// Spring中配置CGLIB代理
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // 使用CGLIB代理
public class AppConfig {
    // 配置AOP
}

总结

CGLIB是处理"没有实现接口的类"动态代理的绝佳工具,特别适合:

  • 为普通类(无接口)添加功能
  • 需要高性能的代理场景
  • AOP实现中需要代理具体类的情况

它的核心优势在于无需接口,通过字节码生成实现代理,性能优于JDK动态代理。不过使用时要注意final类和final方法的限制。