经过上面两部分,我们已经定位到切面,并且织入到代理对象中。接下来我们就看下切面的调用逻辑吧。
对于动态代理而言,当我们调用接口的方法的时候,会进入到代理对象的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的本意可能就是希望用户自定义的去实现通知的逻辑,所以就不与系统的默认通知进行同时使用了