April 20, 2018

spring AOP原理之:

切面的优先级怎么实现

上篇文章讲完了AbstractAutoProxyCreator增强器的创建和匹配,接下来继续讲解切面的优先级。

1. 如果一个实例同时匹配到2个以上的增强器,哪个增强器生效?

增强器的order属性越小,优先级就越高。

为了验证AOP切面顺序,我们写2个增强器:

1. QueryCacheMethodPointcutAdvisor:

2. UpdateCacheMethodPointcutAdvisor:

然后设置QueryCacheMethodPointcutAdvisor的order比UpdateCacheMethodPointcutAdvisor的order大1:

然后在SysUserServiceImpl#getUserInfo方法同时加上@ObjCache和@ObjCacheUpdate注解:

然后分别在QueryCacheInterceptor和UpdateCacheInterceptor打印方法执行日志:

可以看到ObjCache注解的拦截器queryCacheInterceptor,先于@ObjCacheUpdate注解的拦截器updateCacheInterceptor执行。

2. 切面们在哪里进行排序?

上篇文章我们说过,在doCreateBean方法中,每个bean的初始化完成后会找到所有匹配的增强器,然后进行排序,

排序方法AspectJAwareAdvisorAutoProxyCreator#sortAdvisors:

可以看到,queryCacheInterceptor确实是排在updateCacheInterceptor前面。

3. 增强器们排序后如何执行?

老铁们可能会说,这个还不简单,在拿到排序好的增强器列表后,遍历执行一遍,增强器们都完成了目标对象的代理,皆大欢喜,收工走人。实际上spring框架也是这么做的:

1.首先AbstractAutoProxyCreator#createProxy方法创建代理,advisors就是排序好的增强器列表:

2.然后进入CglibAopProxy#getProxy方法,在使用Enhancer创建完代理对象后,需要获取并设置它的callbackTypes:

3.callbackTypes通过getCallbacks方法创建,需要创建CglibAopProxy.DynamicAdvisedInterceptor对象,并将advised参数传入,advised参数中的advisors就是排序好的增强器列表,该方法同时返回Callback数组给Enhancer对象使用:

CglibAopProxy.DynamicAdvisedInterceptor是一个按照spring AOP标准实现的增强器拦截类,,我们调用下SysUserServiceImpl#getUserInfo方法,能发现它被DynamicAdvisedInterceptor#intercept方法拦截:

intercept方法最后创建一个CglibAopProxy.CglibMethodInvocation对象,并执行proceed方法:

CglibAopProxy.CglibMethodInvocation类的父类是ReflectiveMethodInvocation,ReflectiveMethodInvocation实现MethodInvocation接口,并重写了proceed方法,该方法负责遍历增强器列表interceptorsAndDynamicMethodMatchers,并执行链式调用:

可以看到在proceed方法中遍历每个MethodInterceptor对象执行invoke方法,并传入this(也就是调用者本身,ReflectiveMethodInvocation对象,我们标注为A),此时遍历到queryCacheInterceptor,它执行完后会重新调用invocation.proceed()(A.proceed()),这时候轮到下一个拦截器updateCacheInterceptor进行逻辑处理,从而实现拦截器列表的遍历执行:

总结:1.AOP的实现原理是代理对象执行,2.多个AOP冲突时根据order链式执行。