spring aop(二)

白茶清欢无别事,我在等风也等你。苦酒折柳今相离,无风无月也无你

以JdkDynamicAopProxy(jdk代理)为例

org.springframework.aop.framework.JdkDynamicAopProxy#invoke

调用方法时,进入代理对象的invoke方法

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	List<Object> cached = this.methodCache.get(cacheKey);
	if (cached == null) {
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
		this.methodCache.put(cacheKey, cached);
	}
	return cached;
}

获取方法上的拦截器链,先从缓存找,如果缓存有,直接返回

org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice

获取所有的增强器并遍历,如果是PointcutAdvisor类型,进行匹配,如果能够匹配现在正在调用的方法,把增强器转化为拦截器,将拦截器集合返回,并加入缓存中

if (chain.isEmpty()) {
	Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
	retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}

如果拦截器链为空,通过反射直接调用执行

else {
	MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
	retVal = invocation.proceed();
}

创建一个反射方法调用对象并调用执行

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed

public Object proceed() throws Throwable {
    //  We start with an index of -1 and increment early.
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }

    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;
        if (dm.methodMatcher.matches(this.method, this.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, so we just invoke it: The pointcut will have
        // been evaluated statically before this object was constructed.
        return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}

上面就是递归调用拦截器的关键代码,我们可以看到如果当前索引(currentInterceptorIndex)等于拦截器链(interceptorsAndDynamicMethodMatchers)的最大索引时,通过反射调用当前执行的方法,如果不满足,就获取索引对应的拦截器,并把索引加一,执行拦截器的invoke方法

下面我们看下4个主要拦截器的invoke方法

org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke

public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		return mi.proceed();
	}
	catch (Throwable ex) {
		if (shouldInvokeOnThrowing(ex)) {
			invokeAdviceMethod(getJoinPointMatch(), null, ex);
		}
		throw ex;
	}
}

异常通知的invoke方法

org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke

public Object invoke(MethodInvocation mi) throws Throwable {
	Object retVal = mi.proceed();
	this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
	return retVal;
}

返回通知的invoke方法

org.springframework.aop.aspectj.AspectJAfterAdvice#invoke

public Object invoke(MethodInvocation mi) throws Throwable {
	try {
		return mi.proceed();
	}
	finally {
		invokeAdviceMethod(getJoinPointMatch(), null, null);
	}
}

后置通知的invoke方法

org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor#invoke

public Object invoke(MethodInvocation mi) throws Throwable {
	this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
	return mi.proceed();
}

前置通知的invoke方法

如果这四种切面都实现了的话,在获取完切面那里会进行排序,调用顺序是异常通知->返回通知->后置通知->前置通知
所以执行效果是:
前置通知的invoke方法
执行before方法this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
调用mi.proceed()
这时没有下个拦截器所以执行方法本身AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments)
回到后置通知,执行finally块,执行after方法invokeAdviceMethod(getJoinPointMatch(), null, null);
回到返回通知
如果方法本身执行时抛出异常
1)返回通知向上抛出异常,不会执行返回通知的return方法
2)回到异常通知,catch块接受到异常,执行异常通知的方法invokeAdviceMethod(getJoinPointMatch(), null, ex);
3)结束本次方法调用
如果方法本身执行时没有异常
1)执行返回通知的return方法this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
2)回到异常通知,应为没有异常,catch块不会调用,所以不会执行异常通知的方法
3)结束本次方法调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值