CGLIB(Code Generation Library)是一个代码生成库,主要用于为Java对象提供动态代理。Spring框架在某些情况下使用CGLIB来创建代理对象,以实现AOP(Aspect-Oriented Programming)以及其他功能。
CGLIB代理简介
CGLIB通过生成目标类的子类来创建代理对象。这与标准的Java动态代理(`java.lang.reflect.Proxy`)不同,后者要求目标类必须实现接口。CGLIB可以代理任何普通的类,而不仅仅是接口。
Spring 使用 CGLIB 代理的场景
在Spring中,默认情况下,AOP代理会优先使用JDK动态代理。如果目标对象没有实现任何接口,Spring会退而求其次使用CGLIB来生成代理对象。
具体来说,Spring使用CGLIB代理的场景包括但不限于以下几个:
1. **没有实现接口的类**:当一个类没有实现任何接口时,Spring无法使用JDK动态代理,只能使用CGLIB。
2. **强制使用CGLIB**:即使目标类实现了接口,也可以使用`@EnableAspectJAutoProxy(proxyTargetClass = true)`注解强制Spring使用CGLIB代理。
3. **配置类代理**:Spring为了支持@Configuration类中的@Bean方法调用,通常会使用CGLIB代理这些配置类。
CGLIB代理的原理
CGLIB通过字节码操作来生成代理类,并在运行时加载该类。它使用ASM库直接生成新的类文件,这使得其性能比反射方式更高。以下是CGLIB代理的大致工作流程:
1. **动态生成子类**:CGLIB生成目标类的子类,并覆盖目标类中的方法。
2. **方法拦截**:在代理方法中,CGLIB添加拦截器逻辑,用于在方法调用前后执行特定的拦截器行为。
3. **调用父类方法**:代理方法内部会调用父类(即目标类)的方法,从而实现对原方法的调用。
深入源码
下面我们通过查看Spring AOP部分源码,深入理解Spring是如何使用CGLIB实现代理的。
`ProxyFactory` 类
`ProxyFactory`是Spring AOP框架中用于创建代理对象的重要类。它根据目标对象是否实现接口选择合适的代理策略。
```java public class ProxyFactory extends AdvisedSupport implements AopProxyFactory { // 省略其他代码... @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { return new CglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } } private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) { Class<?>[] interfaces = config.getProxiedInterfaces(); return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.isAssignableFrom(interfaces[0]))); } } ```
在上面的代码中,如果`isProxyTargetClass()`返回true,或者目标类没有实现任何接口,`createAopProxy`方法会返回一个`CglibAopProxy`实例。
`CglibAopProxy` 类
`CglibAopProxy`类负责使用CGLIB创建代理对象。
```java public class CglibAopProxy implements AopProxy, Serializable { // 省略其他代码... @Override public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); } try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); } enhancer.setSuperclass(rootClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised)); enhancer.setCallbacks(getCallbacks(rootClass)); return createProxyClassAndInstance(enhancer, rootClass); } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: Common causes of this problem include using a final class or a non-visible class", ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: Common causes of this problem include using a final class or a non-visible class", ex); } } protected Enhancer createEnhancer() { return new Enhancer(); } protected Object createProxyClassAndInstance(Enhancer enhancer, Class<?> rootClass) { enhancer.setInterceptDuringConstruction(false); Object proxy = enhancer.create(); return proxy; } // 省略其他代码... } ```
在上面的代码中,`getProxy`方法使用CGLIB的`Enhancer`类来创建代理对象。`Enhancer`是CGLIB的核心类,用于生成代理类。
`Enhancer` 类
`Enhancer`类是CGLIB库中的核心类,它负责生成代理类。通过设置回调和过滤器,`Enhancer`可以指定代理对象的行为。
```java public class Enhancer { // 省略其他代码... public Object create() { // 创建并返回代理对象 return createHelper().create(); } private Generator createHelper() { Generator g = new Generator(); g.setSuperclass(superclass); g.setInterfaces(interfaces); g.setCallbacks(callbacks); g.setCallbackFilter(filter); g.setNamingPolicy(namingPolicy); g.setStrategy(strategy); return g; } // 省略其他代码... } ```
在上面的代码中,`create`方法最终调用`Generator`类生成代理对象。
总结
CGLIB代理在Spring框架中扮演了重要的角色,特别是在AOP和配置类代理方面。通过动态生成目标类的子类,CGLIB能够在运行时创建代理对象,并实现方法拦截和增强。理解CGLIB代理的工作原理和Spring中相关源码,可以帮助我们更好地掌握Spring框架的内部机制,提高调试和优化能力。