spring|别再说 Spring AOP 默认用的是 JDK 动态代理( 二 )


我们拿集合里面的 MethodBeforeAdviceInterceptor 来举例看下 , 这个是目标方法执行的前置拦截 , 我们看下它的 invoke 实现 , 有更直观的认识:



invoke 的实现是先执行切入的前置逻辑 , 然后再继续调用 CglibMethodInvocation#proceed(也就是mi.proceed) , 进行下一个 interceptor 的调用 。
总结下 :
Spring 根据 @Before、@After、@AfterReturning、@AfterThrowing 这些注解 。
往集合里面加入对应的 Spring 提供的  MethodInterceptor 实现 。
比如上面的 MethodBeforeAdviceInterceptor, 如果你没用 @Before , 集合里就没有 MethodBeforeAdviceInterceptor。
然后通过一个对象 CglibMethodInvocation 将这个集合封装起来 , 紧接着调用这个对象的 proceed 方法 。
具体是利用 currentInterceptorIndex 下标 , 利用递归顺序地执行集合里面的 MethodInterceptor, 这样就完成了拦截链的调用 。
我截个调用链的堆栈截图 , 可以很直观地看到调用的顺序(从下往上看):



是吧 , 是按照顺序一个一个往后执行 , 然后再一个一个返回 , 就是递归呗 。
然后我再解释下上面的 chain 集合我们看到第一个索引位置的 ExposeInvocationInterceptor。
这个 Interceptor 作为第一个被调用 , 实际上就是将创建的 CglibMethodInvocation 这个对象存入 threadlocal 中 , 方便后面 Interceptor 调用的时候能得到这个对象 , 进行一些调用 。



从名字就能看出 expose:暴露 。
ok , 更多细节还是得自己看源码的 , 应付面试了解到这个程度差不多的 , 上面几个关键点一抛 , 这个题绝对稳了!
Spring AOP 和 AspectJ 有什么区别从上面的题目我们已经知道 , 两者分别是动态代理和静态代理的区别 。
Spring AOP 是动态代理 , AspectJ 是静态代理 。
从一个是运行时织入 , 一个在编译时织入 , 我们稍微一想到就能知道 , 编译时就准备完毕 , 那么在调用时候没有额外的织入开销 , 性能更好些 。
【spring|别再说 Spring AOP 默认用的是 JDK 动态代理】且 AspectJ 提供完整的 AOP 解决方案 , 像 Spring AOP 只支持方法级别的织入 , 而 AspectJ 支持字段、方法、构造函数等等 , 所以它更加强大 , 当然也更加复杂 。