Spring AOP 是 Spring 框架的重要组成部分之一。在非常基础的阶段,spring 框架是基于 IoC 和 AOP 的。在 Spring 的官方课程中有一张幻灯片,上面写着:
AOP 是框架中最重要的部分之一。
理解 Spring 中的 AOP 如何工作的关键点是,当您使用 Spring 编写 Aspect 时,我们会为框架构建一个代理,如果您的 bean 实现了接口,则使用 JDKDynamicProxy;如果您的 bean 实现了接口,则使用 CGLIB bean 没有实现任何接口。请记住,如果您使用 Spring 3.2 之前的版本,则您的类路径中必须包含 cglib 2.2。从 Spring 3.2 开始它就没有用了,因为 cglib 2.2 包含在核心中。
创建 bean 时的框架将创建一个代理来包装您的对象并添加横切关注点职责,例如安全性、事务管理、日志记录等。
以这种方式创建的代理将应用于一个切入点表达式,该表达式对框架进行检测以决定将哪些 bean 和方法创建为代理。与您的代码相比,该建议将承担更多责任。请记住,在此过程中,切入点仅捕获未声明为 final 的公共方法。
现在,在 Spring AOP 中,Aspect 的编织将在容器启动时由容器执行,而在 AspectJ 中,您必须通过修改字节码对代码进行后编译来执行此操作。因此,在我看来,Spring 方法比 AspectJ 更简单、更易于管理。
另一方面,使用 Spring AOP,您无法使用 AOP 的全部功能,因为实现是通过代理完成的,而不是通过修改代码来完成的。
与在 AspectJ 中一样,您可以在 SpringAOP 中使用加载时编织。您可以在 spring 中使用代理和特殊配置、@EnabledLoadWeaving 或 XML 实现此功能。您可以使用名称空间作为示例。但是在 Spring AOP 中你不能拦截所有的情况。例如,Spring AOP 不支持 new 命令。
但是在 Spring AOP 中,您可以通过在 spring 配置 bean 中使用 aspectof 工厂方法从 AspectJ 的使用中受益。
由于 Spring AOP 基本上是从容器创建的代理,因此您只能将 AOP 用于 spring bean。在使用 AspectJ 时,您可以在所有 bean 中使用方面。另一个比较点是调试和代码行为的可预测性。使用 Spring AOP,这项工作全部由 Java 编译器执行,方面是为 Spring bean 创建代理的一种非常酷的方式。在 AspectJ 中,如果您修改代码,您需要更多的编译,并且要了解您的切面在哪里编织可能会很困难。即使在 spring 中关闭编织也更简单:使用 spring 从配置中删除方面,重新启动它就可以工作了。在 AspectJ 中你必须重新编译代码!
在加载时编织中,AspectJ 比 Spring 更灵活,因为 Spring 不支持 AspectJ 的所有选项。但在我看来,如果您想更改 bean 的创建过程,更好的方法是在工厂中管理自定义登录,而不是在加载时编织改变新操作员行为的方面。
希望这张AspectJ和Spring AOP的全景图能帮助你理解这两种药水的区别