白茶清欢无别事,我在等风也等你。苦酒折柳今相离,无风无月也无你
以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)结束本次方法调用