接上一篇spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程继续
6. 代理对象执行过程分析1--构造拦截器链
是如何实现先执行@Before,然后proceed,然后@After 然后@AfterReturning这样的顺序执行过程的呢?
容器中保存了组件的代理对象(cglib增强后的对象),这个对象里面保存了详细信息(比如增强器,目标对象);
6.1 CglibAopProxy.intercept();拦截目标方法的执行
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null;
通用AOP回调。 在目标是动态的或代理未冻结时使用。
接下来看其拦截逻辑
6.2 根据ProxyFactory对象获取将要执行的目标方法拦截器链;
可以获取到proxy中的target
target = getTarget(); if (target != null) { targetClass = target.getClass(); } List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
6.2.1 List<Object> interceptorList保存所有拦截器 有5个
一个默认的ExposeInvocationInterceptor 和 4个增强器;
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
6.2.2 遍历所有的增强器,将其转为Interceptor;
for (Advisor advisor : config.getAdvisors()) {
Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors));
registry.getInterceptors(advisor);
6.2.3 将增强器转为List<MethodInterceptor>;
org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry#getInterceptors
@Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[interceptors.size()]); }
如果是MethodInterceptor,直接加入到集合中
如果不是,使用AdvisorAdapter将增强器转为MethodInterceptor;
转换完成返回MethodInterceptor数组;
这个时候这个chain
拦截器链(每一个增强方法又被包装为方法拦截器,利用MethodInterceptor机制的intercept方法)
6.3 如果没有拦截器链,直接执行目标方法;
retVal = methodProxy.invoke(target, argsToUse);
6.4 如果有拦截器链,把需要执行的目标对象,目标方法,
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
拦截器链等信息传入创建一个 CglibMethodInvocation 对象,
并调用 Object retVal = mi.proceed();
7. 代理对象执行过程分析2--拦截器链触发过程
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
@Override 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); } }
7.1 如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法;
// 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);
后面有一个++ this.currentInterceptorIndex
第0号拦截器就是我们的第一个拦截器ExposeInvocationInterceptor
org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第1号拦截器AspectJAfterThrowing
org.springframework.aop.interceptor. AspectJAfterThrowingAdvice#invoke
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第2号拦截器AfterReturningAdviceInterceptor
org.springframework.aop.interceptor. AfterReturningAdviceInterceptor#invoke
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第3号拦截器AspectJAfterAdvice
org.springframework.aop.framework.adapter. AspectJAfterAdvice#invoke
其又进入到
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中
拿到第4号拦截器MethodBeforeAdviceInterceptor
rg.springframework.aop.framework.adapter. MethodBeforeAdviceInterceptor#invoke
注意:这里的invoke方法有区别了
@Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() ); return mi.proceed(); }
其先调用前调通知方法
console中打印:
div运行。。。@Before:参数列表是:{[1, 0]}
由于已经执行到最后一个拦截器了
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
之后调用目标方法
console打印:
MathCalculator...div...
之后回到第3号拦截器AspectJAfterAdvice
console打印:
div结束。。。@After
之后回到第2号拦截器AfterReturningAdviceInterceptor
由于报错了,那么就直接将异常向上抛出
到第1号拦截器AspectJAfterThrowing
console打印:
div异常。。。异常信息:{java.lang.ArithmeticException: / by zero}
最后到第0号拦截器ExposeInvocationInterceptor
流程图:
7.2 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;
拦截器链的机制,保证增强方法与目标方法的执行顺序;
总结spring aop过程:
1. @EnableAspectJAutoProxy 开启AOP功能
2. @EnableAspectJAutoProxy 会给容器中注册一个组件
AnnotationAwareAspectJAutoProxyCreator
3. AnnotationAwareAspectJAutoProxyCreator是一个后置处理器;
4. finishBeanFactoryInitialization() 初始化剩下的单实例bean
4.1 创建业务逻辑组件MathCalculator和切面组件LogAspects
4.2 AnnotationAwareAspectJAutoProxyCreator这个后置处理器拦截组件的创建过程
4.3 组件创建完之后,根据切点表达式判断组件是否需要增强
把切面的增强方法,包装成增强器(Advisor);给业务逻辑组件创建一个代理对象(cglib/动态代理);
5. 执行目标方法:
5.1 代理对象执行目标方法
5.2 CglibAopProxy.intercept();
5.2.1 得到目标方法的拦截器链(增强器包装成拦截器MethodInterceptor)
5.2.2 利用拦截器的链式机制,依次进入每一个拦截器进行执行;
5.2.3 效果:
正常执行:前置通知-》目标方法-》后置通知-》返回通知
出现异常:前置通知-》目标方法-》后置通知-》异常通知