卷前:Spring大家应该都不陌生,其aop实现也是在项目开发中经常用到的;aspectJ可能听说的比较少,只了解到AOP的实现与aspectJ有着一定的关系,某种意义上都可以说是“面向切面”的。
//切面切入此Aaa类,在A方法B方法都要有前置和后置方法 class Aaa{ public void methodA(){ methodB(); } public void methodB(){ .... } }
AOP方式:
调用A方法,会有A方法的切面效果(前后置通知等),A方法中有调用B方法,那此时B方法也会有B对应的切面效果(前后置通知)吗?
答案是NO!
Spring aop 底层是动态代理,所以受限于这点,有些增强就做不到,比如 调用自己的方法就无法走代理,代理是不会修改底层类字节码的。
解释:此时A方法执行时调用的B方法,因为动态代理的A方法,但是A方法内部调用的B方法还是原始的B方法,this.methoB(),并没有B方法对应的切面进入!
AspectJ方式:
使用AspectJ的方法,会发现无论如何A、B方法的切面效果(前后置通知等)都是生效的,究其原理是底层字节码已经改变了,每个方法的切面效果已经在编译后实现了,但不只是编译后实现,下面来看看aspectJ的几种织入方式,可以更好的理解。
aspectJ的几种织入方式
compile-time、post-compile 和 load-time Weavers
首先了解下AspectJ的几种织入方式,分别是compile-time、post-compile 和 load-time,分别对应着编译期、后编译期、加载期织入
编译期织入
首先是编译期织入,上一篇博客所介绍的方式就是使用的编译期织入。很容易理解,普通的
java源码
+aspectJ特殊语法的‘配置’ 文件 + aspectJ特殊的编译器
,编译时候生成已织入后的.class文件,运行时直接运行即可。后编译期织入
后编译期织入和编译期的不同在于,织入的是class字节码或者jar文件。这种形式,可以织入一个已经织入过一次的切面。同样这种情况也需要
特殊的编译器
加载期织入
加载期顾名思义,是在
类被加载进虚拟机之前
织入,使用这种方式,须使用AspectJ agent。
解释:AspectJ帮助我们在切面编写时能将目标方法通过
- 编译期织入,编译时生成最终.class字节码
- 后编译期织入,编译后的“重复织入”
- 加载期织入,agent,直到类被加载到JVM前织入,在此之前可以做一些其他的工作
需要订正