spring--aop_2_源码分析之CglibAopProxy实现

接着上一篇 https://blog.csdn.net/convict_eva/article/details/81084833
DefaultAopProxyFactory.createAopProxy() 方法生成AopProxy 代理对象。
AopProxy 有两个实现类 JdkDynamicAopProxy,CglibAopProxy。上一篇说的是JdkDynamicAopProxy,这里说 CglibAopProxy
 

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
	
		//目录对象的class
		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.");
		}
		//targetClass 是接口类,使用 JDK来生成 Proxy
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		//如果不是接口类,使用CGLIB 生成代理对象
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

CglibAopProxy 也是AopProxy 的实现,CglibAopProxy 也是 ObjenesisCglibAopProxy 父类,所以入口方法就是 ObjenesisCglibAopProxy.getProxy()方法
这个方法在CglibAopProxy 实现的

CglibAopProxy.getProxy() 源码:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
	}

	try {
		//从advised 中获取目标对象的类对象
		Class rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class proxySuperClass = rootClass;
		if (ClassUtils.isCglibProxyClass(rootClass)) {
			//如果目标对象已经是CGLIB 生成代理对象(就是比较类名称中有 $$ 字符串),那么就取目标对象的父类作为目标对象的类
			proxySuperClass = rootClass.getSuperclass();
			Class[] additionalInterfaces = rootClass.getInterfaces();
			for (Class additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// Validate the class, writing log messages as necessary.
		// 打印出不能代理的方法名,CGLIB 是使用继承实现的,所以final , static 的方法不能被增强
		validateClassIfNecessary(proxySuperClass, classLoader);

		// Configure CGLIB Enhancer...
		//创建并配置 Enhancer,  Enhancer 是CGLIB 主要的操作类
		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader &&
					((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
		//配置超类,代理类实现的接口,回调方法等
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

		// 获取callbasks 
		Callback[] callbacks = getCallbacks(rootClass);
		Class[] types = new Class[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		// fixedInterceptorMap only populated at this point, after getCallbacks call above
		enhancer.setCallbackFilter(new ProxyCallbackFilter(
				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);

		// Generate the proxy class and create a proxy instance.
		//通过 Enhancer 生成代理对象,并设置回调。 
		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);
	}
}

总结:
CGLIB 通过 Enhancer 生成代理类的子类,并使用 DynamicAdvisedInterceptor 封装了增强方法
再把 DynamicAdvisedInterceptor 实现放入到callbacks 中就是通过对callbacks 的封装来完成aop的实现。
当调用代理对象的方法,会被 DynamicAdvisedInterceptor.intercept() 方法拦截。
具体怎么调用这个callbacks 的,我也不知道,猜测是生成代理类的实现有关。

CGLIB 的AOP拦截器实现:
DynamicAdvisedInterceptor 是一个 MethodInterceptor, 所以会调用他的 intercept() 方法

DynamicAdvisedInterceptor.intercept()源码:


@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) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
		target = targetSource.getTarget();
		Class targetClass = (target != null ? target.getClass() : null);
		
		//获取是拦截器链,和JDK中是一样的
		List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		
		//返回值
		Object retVal;
		
		// Check whether we only have one InvokerInterceptor: that is,
		// no real advice, but just reflective invocation of the target.
		if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
			// We can skip creating a MethodInvocation: just invoke the target directly.
			// Note that the final invoker must be an InvokerInterceptor, so we know
			// it does nothing but a reflective operation on the target, and no hot
			// swapping or fancy proxying.
			
			//没有拦截器,就反射调用代理方法
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = methodProxy.invoke(target, argsToUse);
		}
		else {
			// We need to create a method invocation...
			//这个也是和jdk 动态代理实现是类似的,只是MethodInvocation实现类不同而已
			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) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
} 
  

总结:
从这个代码中可以看到,实现方式和jdk 动态代理是一样的,只是方法入口和MethodInvocation 实现类使用的不一样
JdkDynamicAopProxy 入口方法是动态代理的 invoke() 方法,CGLIB 使用的是 DynamicAdvisedInterceptor.intercept() 方法
JdkDynamicAopProxy 使用的MethodInvocation 是  ReflectiveMethodInvocation 子类,CGLIB 使用的是 CglibMethodInvocation。具体的实现参考上一篇就行。

 

你可能感兴趣的:(spring)