@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 标注的类具有双重身份:
- 它是一个普通的 Spring Bean:你可以通过构造函数或字段注入其他 Bean(如 Service 或 Repository)。
- 它是一个切面规则容器:它定义了什么时候(Advice)去拦截哪些对象(Pointcut)。 由于它是 Bean,所以它也受 Spring 容器的管理(默认是单例的)。