AspectJ
AspectJ是Eclipse旗下的一个项目。至于它和Spring AOP的关系,不妨可将Spring AOP看成是Spring这个庞大的集成框架为了集成AspectJ而出现的一个模块。
毕竟很多地方都是直接用到AspectJ里面的代码。典型的比如@Aspect,@Around,@Pointcut注解等等。而且从相关概念以及语法结构上而言,两者其实非常非常相似。比如Pointcut的表达式语法以及Advice的种类,都是一样一样的。
那么,它们的区别在哪里呢?
最大的区别在于两者实现AOP的底层原理不太一样:
Spring AOP: 基于代理(Proxying)
AspectJ: 基于字节码操作(Bytecode Manipulation)
通过编织阶段(Weaving Phase),对目标Java类型的字节码进行操作,将需要的Advice逻辑给编织进去,形成新的字节码。毕竟JVM执行的都是Java源代码编译后得到的字节码,所以AspectJ相当于在这个过程中做了一点手脚,让Advice能够参与进来。
而编织阶段可以有两个选择,分别是加载时编织(也可以成为运行时编织)和编译时编织:
哪种方式更好
先下结论:It Depends.
得根据具体需求,不过我个人认为在对AOP的需求不那么深入和迫切的时候,使用Spring AOP足矣。
毕竟Spring作为一个以集成起家的框架,在设计Spring AOP的时候也是为了减轻开发人员负担而做了不少努力的。它提供的开箱即用(Out-of-the-box)的众多AOP功能让很多开发人员甚至都不知道什么是AOP,就算知道了AOP是Spring的一大基石或者@Transactional和@Cacheable等等常用注解是借助了AOP的力量,但是再深入恐怕就有点勉为其难了。这是优点也是缺点,当需要对AOP的实现做出精细化调整的时候,就会有力不从心的感觉。
这个时候,就可以考虑使用AspectJ。AspectJ的功能更加全面和强大。支持全部的Pointcut类型。
这里进行了一个简单的比较,摘录并简单翻译(括号内是我添加的补充)如下:
Spring-AOP Pros
比AspectJ更简单,不需要使用Load-Time Weaving以及AspectJ编译器(为了Compile-Time Weaving)
当使用@Aspect注解时可以很方便的迁移到AspectJ AOP实现
使用代理模式和装饰模式
Spring-AOP Cons
由于是基于代理的AOP,所以基本上只能选择方法execution这一个Pointcut原语
在类本身中调用另一个方法的时候Aspects不会生效
有一点运行时的额外开销
无法为不是从Spring Factory中创建的对象添加Aspect(只对Spring Bean有效)