卷前: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帮助我们在切面编写时能将目标方法通过

  1. 编译期织入,编译时生成最终.class字节码
  2. 后编译期织入,编译后的“重复织入”
  3. 加载期织入,agent,直到类被加载到JVM前织入,在此之前可以做一些其他的工作