Skip to content

@AspectJ 支持 (@AspectJ support)

@AspectJ 指的是一种将切面声明为带有注解的常规 Java 类的风格。@AspectJ 风格是由 AspectJ 项目 作为 AspectJ 5 版本的一部分引入的。Spring 使用 AspectJ 提供的库进行切入点(Pointcut)的解析和匹配,从而解释与 AspectJ 5 相同的注解。尽管如此,AOP 运行时仍然是纯粹的 Spring AOP,并不依赖于 AspectJ 编译器或织入器(Weaver)。

提示

使用 AspectJ 编译器和织入器可以使用完整的 AspectJ 语言,这在在 Spring 应用中使用 AspectJ 中有详细讨论。

本节摘要

本节涵盖了使用 @AspectJ 进行 AOP 开发的核心步骤和概念:

  • 启用 @AspectJ 支持:介绍如何在 Spring 配置中开启注解驱动的 AOP 功能。
  • 声明切面:如何使用 @Aspect 注解定义一个切面 Bean。
  • 声明切入点:深入探讨切入点表达式语法,定义通知在何处执行。
  • 声明通知:介绍不同类型的通知(Before, After, Around 等)及其实现细节。
  • 引入 (Introductions):如何使用 @DeclareParents 为现有的类添加新接口。
  • 切面实例化模型:讨论切面的生命周期(单例、原型、按 Bean 实例化等)。
  • 一个 AOP 示例:通过一个完整的实例展示上述概念的综合应用。

补充教学

1. 厘清关系:Spring AOP vs. AspectJ 5 注解

这是一个非常容易产生误区的地方:

  • 注解来源:虽然我们在代码里写 @Aspect, @Before, @Around,但这些注解类实际上是由 AspectJ 团队定义的(包含在 aspectjweaver.jar 中)。
  • 解析逻辑:Spring 在启动时会扫描这些注解,并利用 AspectJ 的解析引擎来理解 ${pointcut} 表达式。
  • 执行本质:一旦解析完成,Spring 会将其转换为内部的动态代理逻辑。它并没有在编译时修改你的 .class 文件

2. 为什么选择 @AspectJ 风格?

在 Spring 的早期版本中,我们必须通过实现 MethodInterceptor 接口或编写大量的 XML 配置文件(<aop:config>)来定义切面。

  • 优势:@AspectJ 风格将切面逻辑和切点定义集中在一个 POJO 类中,代码更加内聚,且不具侵入性(你可以把切面类当作一个普通的 Bean)。
  • 现状:这是 90% 以上 Spring 开发者首选的 AOP 实现方式。

3. 环境准备:不可或缺的依赖

要使用 @AspectJ 支持,你的项目中必须包含 aspectjweaver.jar。在 Spring Boot 项目中,通常只需要引入 AOP Starter:

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

如果你发现 @Aspect 注解报红,或者 AOP 逻辑莫名不生效,首要任务就是检查这个依赖是否存在。

4. 切面的“双重身份”

在一个 Spring 应用中,被 @Aspect 标注的类具有双重身份:

  1. 它是一个普通的 Spring Bean:你可以通过构造函数或字段注入其他 Bean(如 Service 或 Repository)。
  2. 它是一个切面规则容器:它定义了什么时候(Advice)去拦截哪些对象(Pointcut)。 由于它是 Bean,所以它也受 Spring 容器的管理(默认是单例的)。

Based on Spring Framework.