spring aop(六)--代理调用机制

一.先看基于JDK的

1.从前文的Proxy.newProxyInstance(classLoader, proxiedInterfaces, this),这里的this就是指自身,一旦代理的方法被调用,就会触发this的invoke方法,即org.springframework.aop.framework.JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	MethodInvocation invocation;
	Object oldProxy = null;
	boolean setProxyContext = false;
	TargetSource targetSource = this.advised.targetSource;
	Class<?> targetClass = null;
	Object target = null;
	try {
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
		//如果目标对象没有重写Object类的equals方法
			return equals(args[0]);
		}
		if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
		//如果目标对象没有重写Object类的hashCode方法
			return hashCode();
		}
		if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
		//使用反射直接进行调用
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}
		Object retVal;
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		target = targetSource.getTarget();
		if (target != null) {
			targetClass = target.getClass();
		}
		//获取拦截链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);		
		if (chain.isEmpty()) {
			//如果没有拦截器,直接调用
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
		}
		else {
			//创建ReflectiveMethodInvocation一个对象
			invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			//通过拦截链来处理这个连接点
			retVal = invocation.proceed();
		}
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			retVal = proxy;
		}
		else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException(
					"Null return value from advice does not match primitive return type for: " + method);
		}
		//返回调用结果
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}
2.再看org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
	//没有拦截器直接调用
		return invokeJoinpoint();
	}

	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// 动态判断拦截器是否匹配
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// 不匹配会递归调用拦截链的下一个拦截器
			return proceed();
		}
	}
	else {
		//如果是一个拦截器,直接调用它的invoke方法
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}



二.再看基于CGLib
1.从前文的先获取回调设置到enhancer后,再生成代理.在org.springframework.aop.framework.CglibAopProxy#getCallbacks方法内通过DynamicAdvisedInterceptor构建回调.
2.一旦代理对象的方法被调用,就会触发org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept方法

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
	Class<?> targetClass = null;
	Object target = null;
	try {
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		target = getTarget();
		if (target != null) {
			targetClass = target.getClass();
		}
		//获取拦截链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		Object retVal;
		if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
			//如果没有拦截器,就直接调用
			retVal = methodProxy.invoke(target, args);
		}
		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) {
			releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}
其中CglibMethodInvocation是继承ReflectiveMethodInvocation,CglibMethodInvocation的proceed()方法没有重写,这与基于JDK的处理是一样的.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值