一、cglib初探
Spring 中的 CGLIB 是 Spring 框架对 CGLIB(Code Generation Library)字节码生成库的内置集成与适配,主要用于实现动态代理功能,尤其适用于代理没有实现接口的类。以下是对 Spring 中 CGLIB 的核心总结:
一、核心作用
类代理的实现:
当目标对象没有实现接口时,Spring AOP 会默认使用 CGLIB 生成目标类的子类代理(通过继承实现),弥补 JDK 动态代理(仅支持接口代理)的局限。
支持 Spring 核心功能:
@Configuration 类的代理:确保 @Bean 方法间调用复用容器中的 Bean 实例。
AOP 增强:为目标类方法添加日志、事务、权限控制等横切逻辑。
生命周期管理:代理类可集成 Spring 的初始化、销毁等生命周期回调。
二、与原生 CGLIB 的区别
维度 原生 CGLIB(net.sf.cglib) Spring 内置 CGLIB(org.springframework.cglib)
包路径 net.sf.cglib org.springframework.cglib
依赖来源 独立引入 cglib:cglib 依赖 内置在 spring-core 模块,无需额外依赖
版本冲突 可能与其他框架的 CGLIB 版本冲突 重新打包后与外部隔离,避免冲突
Spring 兼容性 低(可能与 Spring 机制冲突) 高(深度适配 Spring 代理、类加载等逻辑)
三、核心组件与机制
Enhancer:
生成代理类的核心类,通过 setSuperclass(Class) 指定目标类,setCallback(Callback) 设置拦截器,最终通过 create() 生成代理实例。
MethodInterceptor:
方法拦截器接口,核心方法 intercept(...) 定义增强逻辑,通过 MethodProxy.invokeSuper(proxy, args) 调用目标类的原始方法。
FastClass:
CGLIB 生成的辅助类(如 XXX$$FastClassByCGLIB$$...),通过方法索引替代反射调用,提升代理方法的执行性能。(生成2个)
代理类结构:
生成的代理类命名格式为 目标类名$$EnhancerByCGLIB$$随机哈希值,是目标类的子类,重写所有非 final 方法并转发给拦截器处理。
四、典型使用场景
Spring AOP 类代理:
当 @Aspect 切面的切入点匹配非接口类时,自动使用 CGLIB 生成代理,执行 @Before、@Around 等通知逻辑。
@Configuration 类代理:
标注 @Configuration 的类会被 CGLIB 代理,确保 @Bean 方法间调用从容器获取实例(而非重复创建),保证单例特性。
自定义类增强:
直接通过 Enhancer 和 MethodInterceptor 实现类的方法增强(如缓存、日志),无需依赖 Spring AOP 上层接口。
五、注意事项
无法代理 final 元素:
final 类不能被继承(无法生成子类代理),final 方法不能被重写(不会执行拦截逻辑)。
避免过度代理:
默认会代理所有非 final 方法,建议通过过滤逻辑(如跳过 toString()、hashCode() 等 Object 方法)减少不必要的增强。
性能考量:
代理类生成时会消耗一定资源,但运行时通过 FastClass 优化调用性能,多次调用时效率优于反射。
与 Spring AOP 的关系:
Spring AOP 的底层代理实现可选择 CGLIB 或 JDK 动态代理,CGLIB 适用于类代理,是 Spring 代理机制的重要补充。
总结
Spring 中的 CGLIB 是对原生 CGLIB 的适配与封装,通过动态生成子类实现类代理,支撑了 Spring AOP、@Configuration 等核心功能。其优势在于无需接口即可代理,且与 Spring 生态深度兼容,是处理类增强场景的关键技术。理解其原理有助于更好地排查代理相关问题(如方法未被增强、重复创建实例等)。
一、关于FastClassByCGLIB:确实存在两个
CGLIB 在生成代理类时,会为目标类和代理类分别生成对应的FastClass,因此通常会看到两个FastClassByCGLIB类:
目标类的 FastClass:如SpringService$$FastClassByCGLIB$$xxx,用于快速调用原始目标类的方法(通过方法索引替代反射)。
代理类的 FastClass:如SpringService$$EnhancerByCGLIB$$xxx$$FastClassByCGLIB$$xxx,用于快速调用代理类自身的方法(如 CGLIB 生成的内部方法)。
作用:两者均通过方法索引映射提升调用性能,避免反射开销。目标类的 FastClass 用于调用原始业务方法,代理类的 FastClass 用于代理内部逻辑的快速调用。
二、关于 AOP 与非 final 方法的代理:"代理所有非 final 方法,但仅增强匹配切入点的方法"
CGLIB 的默认行为:
生成的代理类会重写目标类的所有非 final 方法(因为 final 方法无法被继承重写),这意味着从字节码层面,所有非 final 方法都被 "代理" 了(即方法调用会经过代理类)。
Spring AOP 的运行时匹配:
虽然代理类重写了所有非 final 方法,但并非所有方法都会执行增强逻辑。Spring AOP 通过以下机制控制:
启动时,将@Pointcut表达式解析为MethodMatcher(方法匹配器)。
运行时,当代理方法被调用时,MethodMatcher会判断当前方法是否匹配切入点(如servicePointcut)。
若匹配:执行对应的通知(@Before、@Around等)增强逻辑。
若不匹配:直接通过MethodProxy.invokeSuper(...)调用目标类的原始方法,等同于 "未增强"。
举例说明:
假设UserService有save()(业务方法)和toString()(Object 方法)两个非 final 方法,且切入点为execution(* save(..)):
代理类会同时重写save()和toString()。
调用save()时:匹配切入点,执行增强逻辑(如日志)。
调用toString()时:不匹配切入点,直接执行原始toString()逻辑(无增强)。
总结
FastClassByCGLIB通常有两个,分别对应目标类和代理类,用于提升方法调用性能。
Spring AOP 中,CGLIB 会代理目标类的所有非 final 方法(重写方法并经过代理逻辑),但仅对匹配切入点(如servicePointcut)的方法执行增强,不匹配的方法会直接调用原始逻辑。
这种设计既保证了代理的全面性(避免遗漏需要增强的方法),又通过切入点匹配实现了精准增强,兼顾了灵活性和性能。
二、代理工厂类
package com.fjl.cglib.spring.test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ProxyFactory {@SuppressWarnings ("unchecked")public static <T, R extends MethodInterceptor> T getProxyFactory (Class<T> targetClass, Class<R> interceptorClass) {validateParams (targetClass, interceptorClass);try {R interceptor = createInterceptorInstance (interceptorClass);Enhancer enhancer = new Enhancer ();enhancer.setSuperclass (targetClass); enhancer.setCallback (interceptor); return (T) enhancer.create ();} catch (Exception e) {throw new RuntimeException ("创建代理对象失败", e);}}@SuppressWarnings ("unchecked")public static <T, R extends MethodInterceptor> T getProxyFactory (Class<T> targetClass,Class<R> interceptorClass,Object... targetArgs) {validateParams(targetClass, interceptorClass);try {R interceptor = createInterceptorInstance (interceptorClass);Enhancer enhancer = new Enhancer ();enhancer.setSuperclass (targetClass);enhancer.setCallback (interceptor);Class<?>[] argTypes = new Class [targetArgs.length];for (int i = 0; i < targetArgs.length; i++) {argTypes [i] = targetArgs [i].getClass ();}return (T) enhancer.create (argTypes, targetArgs);} catch (Exception e) {throw new RuntimeException ("创建带参代理对象失败", e);}}private static <T, R extends MethodInterceptor> void validateParams (Class<T> targetClass, Class<R> interceptorClass) {if (targetClass == null) {throw new IllegalArgumentException ("被代理类的 Class 不能为 null");}if (interceptorClass == null) {throw new IllegalArgumentException ("拦截器的 Class 不能为 null");}if (!MethodInterceptor.class.isAssignableFrom (interceptorClass)) {throw new IllegalArgumentException ("拦截器类必须实现 MethodInterceptor 接口");}}private static <R extends MethodInterceptor> R createInterceptorInstance(Class<R> interceptorClass)throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {Constructor<R> constructor = interceptorClass.getDeclaredConstructor ();constructor.setAccessible (true); return constructor.newInstance ();}
}