本文编写于 1298 天前,最后修改于 1297 天前,其中某些信息可能已经过时。
JDK代理
- 调用代理类
$Proxy的方法时,会调用super.h.invoke方法,该方法实际调用的是JdkDynamicAopProxy#invoke方法; - 判断当前方法是
equals方法且实现类未对equals方法进行重新,如果是,就调用JdkDynamicAopProxy#equals方法,返回执行结果; - 判断当前方法是
hashCode方法且实现类未对hashCode方法进行重新,如果是,就调用JdkDynamicAopProxy#hashCode方法,返回执行结果;
- 调用代理类
cglib代理
- 实际调用的是
DynamicAdvisedInterceptor#intercept方法;
- 实际调用的是
调用
AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice方法获取拦截器链chain;- 从
methodCache缓存中查找是否存在目标方法对应的拦截器链; - 如果没有从
methodCache缓存中找到对应的拦截器链,从ProxyFactory中获取目标类对应的类级别增强advisors; 依次遍历所有的增强
advsiors是否与目标方法匹配,该过程与AOP创建过程中的匹配类似;- 如果是
advisor是IntroductionAdvisor引介增强的实现类,那么就进行类级别进行匹配(不常用); - 默认的
InstantiationModelAwarePointcutAdvisorImpl实现的是普通增强PointcutAdvisor接口,使用切点Pointcut进行方法级别的匹配; - 先使用切点表达式和目标类进行匹配,确保类级别满足切点表达式;
遍历当前bean中的所有方法,使用
aspectj提供的方法(SignaturePattern#matchesExactlyMethod),依次对切点表达式对方法进行精确匹配;- 判断方法参数是否匹配;
- 判断方法名称是否匹配;
- 判断方法抛出异常是否匹配;
- 判断方法返回值是否匹配;
- 调用
DefaultAdvisorAdapterRegistry#getInterceptors方法获取advisor中的拦截器; - 调用
InstantiationModelAwarePointcutAdvisorImpl#findAspectJAnnotationMethod方法扫描增强方法上的aspectJ注解; 根据
apectJ注解的类型创建不同的Advice;@Around->AspectJAroundAdvice;@Before->AspectJMethodBeforeAdvice;@After->AspectJAfterAdvice;@AfterReturning->AspectJAfterReturningAdvice;@AfterThrowing->AspectJAfterThrowingAdvice;- 其中
AspectJAfterAdvice、AspectJAroundAdvice、AspectJAfterThrowingAdvice三种Advice都实现了MethodInterceptor接口,因此这三种Advice本身就是拦截器;
- 判断
advice是否实现MethodInterceptor接口,如果advice接口MethodInterceptor接口,就将advice添加到interceptors中,此处会处理@Around、@After、@AfterThrowing三种注解; - 从默认配置的适配器
AdvisorAdapter:MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter中循环判断是否支持当前的Advice,如果支持,就将advice包装为拦截器并放入interceptors中,此处会处理@Before、@AfterReturning两种注解; - 最终将匹配的
Advisor收集到interceptorList,并放到methodCache缓存中,以便下一次从缓存获取;
- 如果是
- 从
- 如果拦截器链
chain为空,则通过反射调用目标方法,将结果返回; - 如果拦截器链
chain不为空,就将拦截器链chain统一封装为MethodInvocation; 调用
ReflectiveMethodInvocation#proceed,执行拦截器链;- 执行拦截器
ExposeInvocationInterceptor#invoke方法,将拦截器链暴露到ThreadLocal中,同一个线程可以通过ThreadLocal获取当前的拦截器链,继续执行下一个拦截器的invoke方法; - 执行拦截器
AspectJAfterThrowingAdvice#invoke方法,该方法继续执行下一个拦截器的invoke方法,并对invoke方法进行try...catch代码块包裹; - 执行拦截器
AfterReturningAdviceInterceptor#invoke方法,该方法继续执行下一个拦截器的invoke方法,并在invoke方法后执行AfterReturning增强; - 执行拦截器
AspectJAfterAdvice#invoke方法,该方法继续执行下一个拦截器的invoke方法,并finally语句块中执行After增强; - 执行拦截器
AspectJAroundAdvice#invoke方法,该方法会先执行Around前置增强,接着继续执行下一个拦截器的invoke方法,并在方法后执行Around后置增强; - 执行拦截器
MethodBeforeAdviceInterceptor#invoke方法,该方法会先执行Before增强; - 执行目标方法;
- 拦截器
AspectJAroundAdvice执行Around后置增强; - 拦截器
AspectJAfterAdvice在finally语句块中执行After增强; - 拦截器
AfterReturningAdviceInterceptor,如果没有异常发生,就执行AfterReturning增强,并跳过步骤11执行步骤12; - 拦截器
AspectJAfterThrowingAdvice的try...catch代码块如果捕捉到异常并且和@AfterThrowing注解中指定的异常类型一致则执行AfterThrowing增强; - 拦截器
ExposeInvocationInterceptor还原ThreadLocal,停止暴露拦截器链;
- 执行拦截器
- 返回执行结果。