面向切面编程与 Spring
面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP)。在 OOP 中,模块化的关键单元是类,而在 AOP 中,模块化的单元是切面。切面使得能够对跨多个类型和对象的关注点(例如事务管理)进行模块化。(在 AOP 文献中,这些关注点通常被称为“横切”关注点。)
Spring 的一个关键组件是 AOP 框架。虽然 Spring IoC 容器并不依赖于 AOP(这意味着如果你不想使用 AOP,你可以不使用它),但 AOP 补充了 Spring IoC,以提供一个非常强大的中间件解决方案。
AOP 在 Spring 框架中用于:
-
提供声明式企业服务。最重要的服务是 声明式事务管理。
-
让用户实现自定义切面,补充他们对面向对象编程(OOP)的使用与面向切面编程(AOP)。
如果您只对通用声明式服务或其他预打包的声明式中间件服务(例如连接池)感兴趣,您无需直接使用 Spring AOP,可以跳过本章的大部分内容。
章节摘要
AOP 概念
让我们开始定义一些核心的 AOP 概念和术语。这些术语并不是特定于 Spring 的。不幸的是,AOP 术语并不是特别直观。然而,如果 Spring 使用自己的术语,那将更加令人困惑。
Spring AOP 的能力和目标
Spring AOP 是用纯 Java 实现的。无需特殊的编译过程。Spring AOP 不需要控制类加载器层次,因此适合在 servlet 容器或应用服务器中使用。
AOP 代理
Spring AOP 默认使用标准 JDK 动态代理来创建 AOP 代理。这使得任何接口(或一组接口)都可以被代理。
@AspectJ 支持
7 个项目
基于模式的 AOP 支持
如果您更喜欢基于 XML 的格式,Spring 还提供了使用 aop 命名空间标签定义切面的支持。与使用 @AspectJ 风格时相同的切入点表达式和通知类型都得到了支持。因此,在本节中,我们将重点关注该语法,并将读者引导到上一节的讨论(@AspectJ 支持),以理解如何编写切入点表达式和通知参数的绑定。
选择使用哪种 AOP 声明风格
一旦你决定某个方面是实现特定需求的最佳方法,你如何在使用 Spring AOP 或 AspectJ 之间进行选择,以及在 Aspect 语言(代码)风格、@AspectJ 注解风格或 Spring XML 风格之间进行选择?这些决策受到多个因素的影响,包括应用程序需求、开发工具以及团队对 AOP 的熟悉程度。
混合方面类型
完全可以通过使用自动代理支持、模式定义的 aop:aspect 切面、声明的 aop:advisor 顾问,甚至在同一配置中使用其他风格的代理和拦截器来混合 @AspectJ 风格的切面。所有这些都是通过使用相同的底层支持机制实现的,并且可以毫无困难地共存。
代理机制
Spring AOP 使用 JDK 动态代理或 CGLIB 来为给定的目标对象创建代理。JDK 动态代理是内置于 JDK 中的,而 CGLIB 是一个常见的开源类定义库(重新打包到 spring-core 中)。
程序化创建 @AspectJ 代理
除了通过使用 aop:config 或 aop:aspectj-autoproxy 在配置中声明切面外,还可以通过编程方式创建代理来建议目标对象。有关 Spring 的 AOP API 的完整细节,请参见下一章。在这里,我们想要重点关注使用 @AspectJ 切面自动创建代理的能力。
在 Spring 应用程序中使用 AspectJ
到目前为止,我们在本章中讨论的内容都是纯 Spring AOP。在本节中,我们将探讨如何使用 AspectJ 编译器或织入器,而不是仅仅依赖于 Spring AOP,或者在 Spring AOP 的基础上进行扩展,以满足更复杂的需求。
进一步资源
有关 AspectJ 的更多信息可以在 AspectJ 网站上找到。