
CGLIB是一个强大的、高性能的代码生成库。它被广泛应用于AOP(面向切面编程)、ORM(对象关系映射)和其他一些框架中。
CGLIB代理的基本原理:
ASM字节码操作框架,在运行时动态生成目标类的子类。这个子类会继承自目标类。final的方法。覆盖的方法会委托给一个用户定义的拦截器(MethodInterceptor),拦截器中包含了增强的代码。CGLIB代理的特点:
CGLIB通过操纵字节码,创建出目标类的子类,并在子类中覆盖非final的方法,从而实现方法拦截和增强。
CGLIB创建代理类的基本步骤:
CGLIB代理不需要目标类实现任何接口,因为它是通过继承的方式来实现代理的。Enhancer是CGLIB中的一个核心类,用于创建代理类。首先创建一个Enhancer实例,并设置其父类(即目标类)。Callback是一个接口,用于定义代理类中覆盖方法的逻辑。通常使用MethodInterceptor接口,它允许我们在调用原始方法之前和之后插入自定义代码。将实现的Callback对象设置给Enhancer。Enhancer的create()方法,CGLIB会使用ASM字节码操作框架来动态生成一个继承自目标类的子类。这个子类会覆盖所有非final的方法,并将调用委托给Callback对象。create()方法返回的是一个代理类的实例,这个实例可以被当作目标类的实例来使用。当调用代理类的方法时,实际上会调用MethodInterceptor中的intercept()方法。intercept()方法中,可以调用Method对象的invoke()方法来执行原始方法。这样,我们就可以在原始方法执行前后插入自定义的逻辑,实现方法的拦截和增强。AdvisedSupport advised:存储了AOP配置信息的数据结构,如目标对象、切面等。Callback callback:CGLIB 回调对象,负责实现代理逻辑。CglibAopProxy(AdvisedSupport config):构造方法接收一个 AdvisedSupport 参数,用于设置AOP配置信息。getProxy(ClassLoader classLoader):生成代理对象的核心方法,接收一个 ClassLoader 参数用于加载代理类。createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks):使用 CGLIB 的 Enhancer 创建代理类,并返回代理对象的实例。proxy(ClassLoader classLoader, Callback[] callbacks):创建代理类并生成代理对象的实现逻辑, 使用 Enhancer 创建代理类,并指定 Callback 对象,完成代理类的生成和实例化。createEnhancer():创建 Enhancer 对象,用于生成代理类, Enhancer 是 CGLIB 中负责生成代理类的核心类。仅展示部分源码,其它源码会在下方解决其它问题时会出现,没有出现的,读者感兴趣可以自行去解读源码。

代理对象的创建过程: 检查是否可以使用缓存的代理对象 -> 准备 CGLIB Enhancer -> 配置 Enhancer -> 设置回调处理器(Callback) -> 生成代理类字节码 -> 创建代理对象实例 -> 将代理对象缓存起来
Enhancer 对象通过调用 create() 方法来生成代理对象。

createHelper() 方法用来实际创建代理对象。

AbstractClassGenerator 对象通过调用 create() 方法,根据给定的键值(key)创建对象实例。

createProxyClassAndInstance 负责创建代理类的实例,使用 CGLIB 技术创建代理对象,并将指定的拦截器回调方法应用于代理对象上。

通过
ReflectiveMethodInvocation类了解到在 Spring 框架中如何构建和执行代理链,以及拦截器如何在拦截器链中协作,以实现对目标方法的拦截和处理。
在拦截器链中如何依次执行拦截器,并通过判断和调用不同的拦截器或目标方法来实现拦截和处理逻辑。

invokeJoinpoint()用于执行目标方法,如果拦截器链中已经没有下一个拦截器了,或者拦截器中的某个拦截器选择不继续执行拦截器链,那么就会调用这个方法来执行目标方法。

定义了方法拦截器的标准,任何实现该接口的类都可以作为 Spring AOP 中的拦截器,用于在目标方法执行前后添加额外的逻辑。

假设有一个简单的服务类
UserService,其中包含一些方法,希望能够在调用这些方法之前和之后记录日志。使用CGLIB来实现一个拦截器,记录方法调用的开始和结束时间。
public class UserService { public void createUser(String username) { System.out.println("Creating user: " + username); // 模拟创建用户的逻辑 } public void updateUser(String username) { System.out.println("Updating user: " + username); // 模拟更新用户的逻辑 } } /** * 创建 LoggingInterceptor 类,实现 MethodInterceptor 接口 */ public class LoggingInterceptor implements MethodInterceptor { /** * 参数:obj 是被代理的对象实例 * method 是被调用的方法对象 * args 是方法的参数数组 * proxy 是用于调用父类(被代理类)方法的代理对象 */ public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 获取方法调用开始时的时间戳 long startTime = System.currentTimeMillis(); System.out.println("Method " + method.getName() + " start at: " + startTime); // 调用被代理类的原始方法,而不是代理对象的方法,以避免循环调用 Object result = proxy.invokeSuper(obj, args); // 获取方法调用结束时的时间戳 long endTime = System.currentTimeMillis(); System.out.println("Method " + method.getName() + " end at: " + endTime); // 方法执行所花费的时间 System.out.println("Method " + method.getName() + " execution time: " + (endTime - startTime) + " milliseconds"); // 调用原始方法后的返回值 return result; } public static void main(String[] args) { UserService userService = new UserService(); // 使用CGLIB的 Enhancer 类创建了 UserService 类的代理对象,并将拦截器设置为回调方法 Enhancer enhancer = new Enhancer(); // 设置了要代理的目标类是 UserService enhancer.setSuperclass(UserService.class); // 指定了在方法调用时应该执行的拦截逻辑 enhancer.setCallback(new LoggingInterceptor()); // 创建代理对象,将会在方法调用时执行我们定义的拦截逻辑 UserService userServiceProxy = (UserService) enhancer.create(); // 调用代理对象的 createUser 和 updateUser 方法来触发拦截器的拦截逻辑 userServiceProxy.createUser("John Doe"); userServiceProxy.updateUser("Jane Smith"); } } //输出结果: Method createUser start at: 1621802728000 Creating user: John Doe Method createUser end at: 1621802728000 Method createUser execution time: 0 milliseconds Method updateUser start at: 1621802728000 Updating user: Jane Smith Method updateUser end at: 1621802728000 Method updateUser execution time: 0 milliseconds 实现对非接口类的代理和增强功能通常使用 Spring AOP来实现,提供了一种便捷的方式来在方法执行前、执行后、方法抛出异常时等时机插入特定逻辑,而无需修改原始类的代码。
假设有一个订单管理系统,其中包含一个 OrderService 类,该类负责处理订单相关的业务逻辑,比如创建订单、更新订单状态等。希望在处理订单相关业务时,记录日志并统计方法执行时间。
@Aspect @Component public class OrderAspect { /** * 切面方法,用于实现切面的逻辑 -> 表示正在执行目标方法之前 * 接受一个 JoinPoint 参数,连接点 -> 被增强的目标方法 */ @Before("execution(* com.example.service.OrderService.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Before executing method: " + joinPoint.getSignature()); } /** * 切面方法,用于实现切面的逻辑 -> 表示目标方法执行完成后 * 接受一个 JoinPoint 参数,连接点 -> 被增强的目标方法 */ @After("execution(* com.example.service.OrderService.*(..))") public void logAfter(JoinPoint joinPoint) { System.out.println("After executing method: " + joinPoint.getSignature()); } } /** * 标识这个类是一个配置类 -> 告诉 Spring 容器如何配置应用程序上下文 * 启用了 AspectJ 自动代理 -> 告诉 Spring 在运行时生成 AOP 代理以支持 @AspectJ 切面 * 指示 Spring 在包 com.example 及其子包中扫描组件 -> 自动发现并注册带有 @Component、@Service、@Repository 和 @Controller 注解的 bean */ @Configuration @EnableAspectJAutoProxy @ComponentScan(basePackages = "com.example") public class AppConfig { } /** * 调用 OrderService 类的 createOrder() 或 updateOrderStatus() 方法时,OrderAspect 切面中定义的增强逻辑会在方法执行前后生效,从而实现了对非接口类的代理和增强功能 */ @Service public class OrderService { public void createOrder() { // 模拟创建订单的业务逻辑 System.out.println("Creating order..."); } public void updateOrderStatus() { // 模拟更新订单状态的业务逻辑 System.out.println("Updating order status..."); } } // 输出结果: Before executing method: public void com.example.service.OrderService.createOrder() Creating order... After executing method: public void com.example.service.OrderService.createOrder() Before executing method: public void com.example.service.OrderService.updateOrderStatus() Updating order status... After executing method: public void com.example.service.OrderService.updateOrderStatus() 对乐于苦斗的人来说,苦斗不是憾事,而是乐事