Spring Aop 到底做了什么?
序
最近几天在工作中遇到了一个动态代理所带来的坑,遂简单的研究了一波aop执行流程的源码,希望对各位有所帮助。
对于AOP执行顺序不清楚的jym,可以看一下这篇文章:Spring AOP 执行顺序问题
文章结构
本文想以一个问题提出AOP动态代理的问题,通过问题的思考,以一个简单的例子来解读Spring AOP大致做了什么,最后再做一波总结。
简单的问题
简单的切面类
简单的代理类
问题其实很简单,this.dy2()会不会走切面,打印出before?
答案是:不会
。
答案有些朋友有可能答对了,但是为什么呢?
我当时错误的思考是,controller对象已经是cglib动态代理的对象了,也就是增强对象了,dy()方法走切面肯定是不会有问题的,但是为什么dy2()不走切面呢?this对象不是已经代理过的增强的controller么,那么dy2()方法应该也是增强的,必然也会走切面,为什么最后却不走切面呢?
思考中。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
解答:首先一开始就已经搞错了,this对象
和增强后的controller对象
本来就不是同一个对象,this对象只是controller对象本身
。你可以直接从spring容器中获取增强后的controller然后与this进行对比就会发现他们并不是同一个对象。
为什么会这样呢?
简单的源码分析
在这里我只会做关键地方和本文有关的源码解读,以后我会写一篇详细的Spring AOP执行流程的源码分析
和Spring创建动态代理源码分析
。
首先Spring的AOP采用的动态代理是jdk
和cglib
。
对应的接口是AopProxy
,对应的类是CglibAopProxy
和JdkDynamicAopProxy
。
本文以CglibAopProxy
来做相关分析。
这个方法里面的东西很多,以及后续的涉及东西也会很多,所以我会直接定位到最关键的地方忽略掉很多东西,只是为了定位到反射掉用自己类的地方,然后证明所谓的切面也就是一层一层的执行对应的增强方法,最后反射再掉用自己的实际方法,所以这就证明了一点那就是上述controller中的this其实就是它本身的而不是增强的对象。
target为什么是未增强的对象呢?这要涉及到bean动态代理的源码,我也大致截一下图方便理解。
总结
源码的分析十分的粗糙,但也只是为了证明 不管是jdk还是cglib动态代理确实是动态生成了代理类,但是代理类执行增强方法的时候只是判断是否有切面,然后按照切面顺序执行切面方法,最后通过反射来调用实际方法,而反射的对象确是原本的对象而不是增强后的代理对象。
尾
非常感谢能看到这里的JYM,如果本文有误请不吝赐教。
转载自:https://juejin.cn/post/7160960846032535560