下面是Spring AOP大致类图。
- Advice
Advice接口表示增强,定义在连接点做什么。
Advice接口派生出三个接口:BeforeAdvice,AfterAdvice和Intercepter。BeforeAdvice用于前置通知,定义了在方法调用前的before方法。AfterAdvice定义了在目标对象方法调用之后的afterReturning回调。Interceptor主要用于封装Advice对象。用于向目标对象方法织入Advice通知。 - Pointcut
Pointcut 接口用来表示切点,切点决定增强应该作用于哪个连接点。切面本质上是每一个方法调用,选择切面的过程实际上就是选择方法的过程。其中派生出的ReflectiveMethodInvocation实现对拦截器的调用。下面我们看看其proceed方法。
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//没有拦截器,直接调用Joinpoint的method,即直接调用
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//获取拦截器链上第i个拦截器
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;
//当前拦截器是符合拦截规则,每个拦截器可以定义是否特定的类和方法名是否符合拦截规则
//实际上PointCut定义的方法签名最后会转换成这个MethodMatcher,并置于拦截器中
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.
//当前方法不需要拦截,递归调用proceed方法
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
//如果是一个interceptor,直接调用这个interceptor方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
在proceed方法中,会迭代运行拦截器的拦截方法。在执行proceed方法会传递MethodInvocation参数给invoke方法,invoke方法会执行MethodInvocation对象的proceed方法。实现循环递归调用,直至遍历完所有的拦截器链对象。下面是MethodBeforeAdviceInterceptor的invoke方法。
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
这是我个人理解,后续会继续更新,敬请期待。
参考资料:
计文柯《spring技术内幕》