spring aop源码解析3: 代理对象执行过程分析--构造拦截器链及触发拦截器链

spring aop的源码解析内容比较多,分为三个部分:

1. 创建、初始化并注册AnnotationAwareAspectJAutoProxyCreator

参考:spring aop源码解析1: 创建、初始化并注册AnnotationAwareAspectJAutoProxyCreator

2. AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

参考:spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

3. 代理对象执行过程分析--构造拦截器链及触发拦截器链

参考:spring aop源码解析3: 代理对象执行过程分析--构造拦截器链及触发拦截器链

这一篇为第三篇。

接上一篇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保存所有增强器advice,有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

 

详细分析这个递归过程

7.1.1 第0号拦截器

第0号拦截器就是我们的第一个拦截器ExposeInvocationInterceptor

org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke

7.1.2 第1号拦截器

其又进入到

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中

拿到第1号拦截器AspectJAfterThrowing

org.springframework.aop.interceptor. AspectJAfterThrowingAdvice#invoke

7.1.3 第2号拦截器

其又进入到

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中

拿到第2号拦截器AfterReturningAdviceInterceptor

7.1.4 第3号拦截器

org.springframework.aop.interceptor. AfterReturningAdviceInterceptor#invoke

其又进入到

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中

拿到第3号拦截器AspectJAfterAdvice

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

7.1.5 第4号拦截器(最后的一个拦截器)

其又进入到

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed中

拿到第4号拦截器MethodBeforeAdviceInterceptor

org.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 效果:

正常执行:前置通知-》目标方法-》后置通知-》返回通知

出现异常:前置通知-》目标方法-》后置通知-》异常通知

 

遗留的部分:在这三篇spring aop源代码解析中,忽略了一块内容,就是对aop xml的解析形成beanDefinition的部分,也没有讲如何对@Aspect,@Pointcut这些内容进行解析生成beanDefinition部分,这一块的设计在刘欣老师的spring aop课程中有简化实现。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值