spring-aop(下)-方法拦截

经过上面两部分,我们已经定位到切面,并且织入到代理对象中。接下来我们就看下切面的调用逻辑吧。
对于动态代理而言,当我们调用接口的方法的时候,会进入到代理对象的invoke方法中。以jdk的动态代理为例

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	
			//object类型的方法不进行代理
			Object retVal;
            //是否暴露代理对象
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}
	//将advisor转换成拦截器
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
						//调用所有的拦截器
				retVal = invocation.proceed();
			}
		}
	    //invocation的增强具体实现
		public Object proceed() throws Throwable {
		// We start with an index of -1 and increment early.
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		//当所有的增强器都执行完毕的时候,此时我们的index与size()-1是相等的,所以此时我们进行调用目标类的方法
			return invokeJoinpoint();
		}
        //获取当前的增强器/切面/拦截器,因为是排序好的,所以我们可以直接递归使用,否则需要判断具体的方法名和拦截器的生效位置
        //ExposeInvocationInterceptor。存储了当前的ReflectiveMethodInvocation到线程私有变量中。
        //MethodBeforeAdviceInterceptor
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		else {
			// It's an interceptor, seo we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			//传入的参数每次都为当前对象(ReflectiveMethodInvocation),并在子类的实现中在各自合适的实际调用ReflectiveMethodInvocation的proceed方法。实现了不同通知处于不同时机触发的效果。
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}
	1.//org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
	public Object invoke(MethodInvocation mi) throws Throwable {
		MethodInvocation oldInvocation = invocation.get();
		//设置ThreadLocal
		invocation.set(mi);
		try {
			return mi.proceed();
		}
		finally {
			invocation.set(oldInvocation);
		}
	}
	2.//org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor#invoke
		@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
	    //before方法每次都会先执行
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		return mi.proceed();
	}
	3.//org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		finally {
		//after通知在finally快中执行,所以after通知一定会执行
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}
	4.//org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
		@Override
	@Nullable
	public Object invoke(MethodInvocation mi) throws Throwable {
		Object retVal = mi.proceed();
		//当方法执行成功以后执行 afterReturn 通知
		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
		return retVal;
	}
	5.org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke
	public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			return mi.proceed();
		}
		catch (Throwable ex) {
			if (shouldInvokeOnThrowing(ex)) {
			//抛出异常以后,执行afterThrowing通知
				invokeAdviceMethod(getJoinPointMatch(), null, ex);
			}
			throw ex;
		}
	}
	6.// target.method.invoke()

还有一种比较特殊的情况,就是around通知,当我们同时存在around通知和其他通知的时候,发现其余的通知并不会被调用,直接进行到method.invoke()中,由上面通知的触发时机,基本上是围绕着try-catch-finally的时机来进行触发的,around的本意可能就是希望用户自定义的去实现通知的逻辑,所以就不与系统的默认通知进行同时使用了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值