接着上一篇 Spring AOP(六)细究 JdkDynamicAopProxy 类 ,我们来继续分析 Spring 中 CGLIB 代理对象的生成和如何对方法进行增强处理的逻辑。
回到 DefaultAopProxyFactory
类中的 createAopProxy
方法,我们发现有两个 AOP 代理类,除了 JdkDynamicAopProxy
类还有 ObjenesisCglibAopProxy
类。
为了方便阅读,把上文中的 createAopProxy
方法的代码清单再次贴出来。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// config.isOptimize() 这个属性没有研究过
// 满足下面三个条件的任意一个
// 1. 如果 optimize 属性为 ture
// 2. 或者 proxyTargetClass 属性为 ture
// 3. 被代理类没有可代理的接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果被代理类的类型是接口,或者被代理类是 JDK 动态代理生成的代理类,则使用 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用 CGLIB 动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
}
源码分析
下面我们就从 ObjenesisCglibAopProxy
类开始分析,ObjenesisCglibAopProxy
类的代码清单如下所示。
class ObjenesisCglibAopProxy extends CglibAopProxy {
private static final SpringObjenesis objenesis = new SpringObjenesis();
public ObjenesisCglibAopProxy(AdvisedSupport config) {
super(config);
}
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
// 通过 Objenesis 技术实例化代理对象
}
}
可以看到 ObjenesisCglibAopProxy
中就只有实例化代理对象的方法,getProxy()
方法在其父类 CglibAopProxy
类中定义,代码清单如下所示。
public Object getProxy() {
return getProxy(null);
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
// CGLIB 代理类通过继承被代理类实现动态代理
// 1. 获得需要被代理的的类
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
// 如果被代理类已经是被 CGLIB 代理过的了,则代理其父类,避免出现 java.lang.ClassFormatError: Duplicate method name "newInstance" 异常
// 举个例子:rootClass 是 【Spring AOP (三) CGLIB 动态代理】Service 的代理类 Service$$EnhancerByCGLIB$$bdabbd96 ,那么这里的 proxySuperClass 就是 Service
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
// 添加代理类实现的相关接口,addInterface 方法中会对接口做去重处理
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// 2. 配置 CGLIB Enhancer,还记得 【Spring AOP (三) CGLIB 动态代理】 中通过 enhancer 创建代理类的例子吗?
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 设置被代理类为代理类的父类
enhancer.setSuperclass(proxySuperClass);
// 设置代理类需要实现的接口
// AopProxyUtils.completeProxiedInterfaces 方法在 【Spring AOP(六)细研JdkDynamicAopProxy类】中有详细描述,这里就不赘述
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
// 设置 CGLIB 代理类的命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
// 设置 CGLIB 代理类字节码的默认生成策略
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 3. 获取到生成代理类所需的所有 Callback
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// 一个 method 只能被一个 Callback 增强处理
// 4. 存在超过一个 Callback 的情况下,就需要设置 CallbackFilter,用来分配一个 method 由哪个 Callback 增强处理
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 5. 生成代理类并创建代理类实例。
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
接下来分析在 getProxy
方法中一些需要关注的地方。
SpringNamingPolicy
类的代码清单如下所示。
public class SpringNamingPolicy extends DefaultNamingPolicy {
public static final SpringNamingPolicy INSTANCE = new SpringNamingPolicy();
@Override
protected String getTag() {
// DefaultNamingPolicy 中返回 ByCGLIB,
// 所有通过类名我们就可以知道是 Spring 生成的代理类,还是 CGLIB 原生生成的代理类
return "BySpringCGLIB";
}
}
DefaultNamingPolicy
类在 Spring AOP (三) CGLIB 动态代理 一文中已经讨论过了,这里就不再赘述。
getCallbacks
的代码清单如下所示。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 定义一个用于 AOP 调用的 MethodInterceptor (DynamicAdvisedInterceptor)
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// targetInterceptor 是不对方法做增强处理的 MethodInterceptor,直接在 intercept 调用目标对象的目标方法
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// 不需要返回 this 的 method,可以用 StaticDispatcher 进行代理,即直接通过 target 对象调用目标方法
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
// 不需要增强的方法
new SerializableNoOp(),
targetDispatcher,
// 通过 advised 直接调用 Advised 接口的方法
this.advisedDispatcher,
// 专门用来处理 equals 方法的拦截器,和 JdkDynamicAopProxy 类似
new EqualsInterceptor(this.advised),
// 专门用来处理 equals 方法的拦截器,和 JdkDynamicAopProxy 类似
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// 忽略了 isStatic && isFrozen 条件的逻辑处理
callbacks = mainCallbacks;
return callbacks;
}
ProxyCallbackFilter
类的代码清单如下所示,我们主要关注 accept
方法。
// CGLIB callback 数组索引常量
private static final int AOP_PROXY = 0; // DynamicAdvisedInterceptor
private static final int INVOKE_TARGET = 1; // StaticUnadvisedExposedInterceptor或 DynamicUnadvisedExposedInterceptor
private static final int NO_OVERRIDE = 2; // SerializableNoOp
private static final int DISPATCH_TARGET = 3; // StaticDispatcher
private static final int DISPATCH_ADVISED = 4; // AdvisedDispatcher
private static final int INVOKE_EQUALS = 5; // EqualsInterceptor
private static final int INVOKE_HASHCODE = 6; // HashCodeInterceptor
private static class ProxyCallbackFilter implements CallbackFilter {
private final AdvisedSupport advised;
/**
* 实现 CallbackFilter.accept() 以返回我们需要的 Callbacks 数组中的 index 值。
*/
@Override
public int accept(Method method) {
// finalize 方法不需要代理类重写
if (AopUtils.isFinalizeMethod(method)) {
return NO_OVERRIDE;
}
// Advised 接口的方法由 AdvisedDispatcher 增强处理,即直接调用 advised 中的对应方法
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return DISPATCH_ADVISED;
}
// equals 方法由 EqualsInterceptor 代理
if (AopUtils.isEqualsMethod(method)) {
return INVOKE_EQUALS;
}
// hashCode 方法由 HashCodeInterceptor 代理
if (AopUtils.isHashCodeMethod(method)) {
return INVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// chain 不为空,表示当前 method 需要被增强处理
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// 如果公开代理,让其在整个拦截器责任链种可见,则必须使用 AOP_PROXY,即 DynamicAdvisedInterceptor
if (exposeProxy) {
return AOP_PROXY;
}
String key = method.toString();
// 检查我们是否有固定拦截器来增强当前 method。
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
// 通过 FixedChainStaticTargetInterceptor 对拦截器做特定的优化处理
int index = this.fixedInterceptorMap.get(key);
return (index + this.fixedInterceptorOffset);
}
else {
// 否则使用 AOP_PROXY,即 DynamicAdvisedInterceptor
return AOP_PROXY;
}
}
else {
// 如果需要暴露代理对象,或者 target 对象是可变的,则通过 StaticUnadvisedExposedInterceptor 代理
if (exposeProxy || !isStatic) {
return INVOKE_TARGET;
}
// 如果当前方法的返回类型是目标对象的类型,则通过 StaticUnadvisedExposedInterceptor 代理
Class<?> returnType = method.getReturnType();
if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
return INVOKE_TARGET;
}
else {
// 否则,通过 StaticDispatcher 进行代理
return DISPATCH_TARGET;
}
}
}
}
然后我们重点关注 Spring AOP
的实现逻辑,在 DynamicAdvisedInterceptor
类中可以看到完整的代码清单。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// 如果需要在拦截器暴露 proxy 对象,则把 proxy 对象添加到 ThreadLocal 中
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 获取目标对象和目标对象类型
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 获取此方法的拦截器链,这个方法在【Spring AOP(六)细研JdkDynamicAopProxy类】种已经讨论过了,这里就不赘述了
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果拦截器集合为空,说明当前 method 不需要被增强,则通过 methodProxy 直接调用目标对象上的方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 创建 CglibMethodInvocation,用来管理方法拦截器责任链
// 通过 proceed 方法驱动拦截器责任链的运行,并获取到返回值。
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// 把第一次调用 setCurrentProxy 返回的对象,重新设置到 ThreadLocal 中
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
可以看到 DynamicAdvisedInterceptor
类中的 intercept
方法和 JdkDynamicAopProxy
类的 invoke
方法十分类似。
最后,我们再来看下 CglibMethodInvocation
类的详细代码清单。
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
@Nullable
private final MethodProxy methodProxy;
public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
Object[] arguments, @Nullable Class<?> targetClass,
List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
// 仅对非 Object 类的方法使用 methodProxy 进行调用,详见 invokeJoinpoint() 方法
this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
methodProxy : null);
}
/**
* 重写 ReflectiveMethodInvocation 中通过反射调用目标方法的逻辑
*/
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.methodProxy != null) {
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
return super.invokeJoinpoint();
}
}
}
CglibMethodInvocation
类继承了 ReflectiveMethodInvocation
类,并且仅重写了其 invokeJoinpoint()
方法,而 proceed
方法在 Spring AOP(六)细究 JdkDynamicAopProxy 类 中已经详细讲解,所以这里就不再赘述。
至此,Spring 中的 CGLIB AOP 代理 就基本说完了。
(正文完)
扩展阅读
- Spring AOP (一) 简介
- Spring AOP (二) JDK 动态代理
- Spring AOP (三) CGLIB 动态代理
- Spring AOP (四) 多重代理和责任链模式
- Spring AOP(五)切入点和通知
- Spring AOP(六)细究 JdkDynamicAopProxy 类
喜欢本文的朋友们,欢迎关注微信公众号【程序员小课堂】,阅读更多精彩内容!

网友评论