登录后台

页面导航

本文编写于 744 天前,最后修改于 742 天前,其中某些信息可能已经过时。
  1. JDK代理

    1. 调用代理类$Proxy的方法时,会调用super.h.invoke方法,该方法实际调用的是JdkDynamicAopProxy#invoke方法;
    2. 判断当前方法是equals方法且实现类未对equals方法进行重新,如果是,就调用JdkDynamicAopProxy#equals方法,返回执行结果;
    3. 判断当前方法是hashCode方法且实现类未对hashCode方法进行重新,如果是,就调用JdkDynamicAopProxy#hashCode方法,返回执行结果;
  2. cglib代理

    1. 实际调用的是DynamicAdvisedInterceptor#intercept方法;
  3. 调用AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice方法获取拦截器链chain

    1. methodCache缓存中查找是否存在目标方法对应的拦截器链;
    2. 如果没有从methodCache缓存中找到对应的拦截器链,从ProxyFactory中获取目标类对应的类级别增强advisors
    3. 依次遍历所有的增强advsiors是否与目标方法匹配,该过程与AOP创建过程中的匹配类似;

      1. 如果是advisorIntroductionAdvisor引介增强的实现类,那么就进行类级别进行匹配(不常用);
      2. 默认的InstantiationModelAwarePointcutAdvisorImpl实现的是普通增强PointcutAdvisor接口,使用切点Pointcut进行方法级别的匹配;
      3. 先使用切点表达式和目标类进行匹配,确保类级别满足切点表达式;
      4. 遍历当前bean中的所有方法,使用aspectj提供的方法(SignaturePattern#matchesExactlyMethod),依次对切点表达式对方法进行精确匹配;

        1. 判断方法参数是否匹配;
        2. 判断方法名称是否匹配;
        3. 判断方法抛出异常是否匹配;
        4. 判断方法返回值是否匹配;
      5. 调用DefaultAdvisorAdapterRegistry#getInterceptors方法获取advisor中的拦截器;
      6. 调用InstantiationModelAwarePointcutAdvisorImpl#findAspectJAnnotationMethod方法扫描增强方法上的aspectJ注解;
      7. 根据apectJ注解的类型创建不同的Advice;

        • @Around -> AspectJAroundAdvice
        • @Before -> AspectJMethodBeforeAdvice
        • @After -> AspectJAfterAdvice
        • @AfterReturning -> AspectJAfterReturningAdvice
        • @AfterThrowing -> AspectJAfterThrowingAdvice
        • 其中AspectJAfterAdviceAspectJAroundAdviceAspectJAfterThrowingAdvice三种Advice都实现了MethodInterceptor接口,因此这三种Advice本身就是拦截器;
      8. 判断advice是否实现MethodInterceptor接口,如果advice接口MethodInterceptor接口,就将advice添加到interceptors中,此处会处理@Around@After@AfterThrowing三种注解;
      9. 从默认配置的适配器AdvisorAdapterMethodBeforeAdviceAdapterAfterReturningAdviceAdapterThrowsAdviceAdapter中循环判断是否支持当前的Advice,如果支持,就将advice包装为拦截器并放入interceptors中,此处会处理@Before@AfterReturning两种注解;
      10. 最终将匹配的Advisor收集到interceptorList,并放到methodCache缓存中,以便下一次从缓存获取;
  4. 如果拦截器链chain为空,则通过反射调用目标方法,将结果返回;
  5. 如果拦截器链chain不为空,就将拦截器链chain统一封装为MethodInvocation
  6. 调用ReflectiveMethodInvocation#proceed,执行拦截器链;

    1. 执行拦截器ExposeInvocationInterceptor#invoke方法,将拦截器链暴露到ThreadLocal中,同一个线程可以通过ThreadLocal获取当前的拦截器链,继续执行下一个拦截器的invoke方法;
    2. 执行拦截器AspectJAfterThrowingAdvice#invoke方法,该方法继续执行下一个拦截器的invoke方法,并对invoke方法进行try...catch代码块包裹;
    3. 执行拦截器AfterReturningAdviceInterceptor#invoke方法,该方法继续执行下一个拦截器的invoke方法,并在invoke方法后执行AfterReturning增强;
    4. 执行拦截器AspectJAfterAdvice#invoke方法,该方法继续执行下一个拦截器的invoke方法,并finally语句块中执行After增强;
    5. 执行拦截器AspectJAroundAdvice#invoke方法,该方法会先执行Around前置增强,接着继续执行下一个拦截器的invoke方法,并在方法后执行Around后置增强;
    6. 执行拦截器MethodBeforeAdviceInterceptor#invoke方法,该方法会先执行Before增强
    7. 执行目标方法
    8. 拦截器AspectJAroundAdvice执行Around后置增强
    9. 拦截器AspectJAfterAdvicefinally语句块中执行After增强;
    10. 拦截器AfterReturningAdviceInterceptor,如果没有异常发生,就执行AfterReturning增强,并跳过步骤11执行步骤12
    11. 拦截器AspectJAfterThrowingAdvicetry...catch代码块如果捕捉到异常并且和@AfterThrowing注解中指定的异常类型一致则执行AfterThrowing增强;
    12. 拦截器ExposeInvocationInterceptor还原ThreadLocal,停止暴露拦截器链;
  7. 返回执行结果。