1、简介 {#1简介}
本文将带你了解 Spring 中的 AOP(面向切面编程),并学习如何在实际场景中使用这一强大工具。
在使用 Spring AOP 开发时,还可以利用 @AspectJ
的注解,但本文重点介绍 Spring AOP 基于 XML 的核心配置。
2、概览 {#2概览}
AOP 是一种编程范式,旨在通过分离横切关注点来提高模块化程度。它通过在不修改代码本身的情况下为现有代码添加额外的行为来实现这一目标。
Spring 的 AOP 框架 可以帮助我们实现这些切面关注点。
3、Maven 依赖 {#3maven-依赖}
首先,在 pom.xml
中添加 Spring 的 AOP 依赖:
<!-- Spring Boot 应用 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
<!-- Spring 应用 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>6.1.1</version>
</dependency>
</dependencies>
可以在 Maven 仓库中查询到最新的版本。
4、AOP 概念和术语 {#4aop-概念和术语}
简要回顾一下 AOP 的特定概念和术语:
4.1、业务对象 {#41业务对象}
业务对象是一个具有正常业务逻辑的普通类。
来看一个简单的业务对象示例,只需将两个数字相加:
public class SampleAdder {
public int add(int a, int b) {
return a + b;
}
}
注意,该类是一个包含业务逻辑的普通类,没有任何与 Spring 相关的注解。
4.2、切面 {#42切面}
切面(Aspect)是对跨多个类的关注点的模块化。统一日志就是这种跨类问题的一个例子。
定义一个简单的切面:
public class AdderAfterReturnAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public void afterReturn(Object returnValue) throws Throwable {
logger.info("value return was {}", returnValue);
}
}
在上面的示例中,定义了一个简单的 Java 类,它有一个名为 afterReturn
的方法,该方法接收一个 Object
类型的参数并记录该值。注意,AdderAfterReturnAspect
也是一个标准类,没有任何 Spring 注解。
接下来将带你了解如何将此 Aspect
连接到业务对象。
4.3、Joinpoint {#43joinpoint}
Joinpoint
(连接点)是程序执行过程中的一个点,如方法的执行或异常的处理。
在 Spring AOP 中,JoinPoint
始终代表一个方法的执行。
4.4、Pointcut {#44pointcut}
切点(Pointcut
)是一个 Predicate
,帮助匹配一个通知(Advice
)在特定的连接点(JoinPoint
)上由一个切面(Aspect)应用。
通常我们将通知(Advice
)与切点表达式关联起来,并且它会在切点(Pointcut
)匹配的任何连接点(Joinpoint
)上运行。
4.5、Advice {#45advice}
通知(Advice
)是切面在特定连接点上执行的操作。不同类型的通知包括 around
(环绕通知)、before
(前置通知)和 after
(后置通知)。
在 Spring 中,Advice
被建模为拦截器(Interceptor),它维护着一个环绕连接点的拦截器链。
4.6、将业务对象(Business Object)和切面(Aspect)进行连接 {#46将业务对象business-object和切面aspect进行连接}
现在来看看如何将一个业务对象与一个具有后置通知(After-Returning Advice)的切面进行连接。
下面是标准 Spring 配置中 <beans>
标签的配置:
<bean id="sampleAdder" class="org.baeldung.logger.SampleAdder" />
<bean id="doAfterReturningAspect"
class="org.baeldung.logger.AdderAfterReturnAspect" />
<aop:config>
<aop:aspect id="aspects" ref="doAfterReturningAspect">
<aop:pointcut id="pointCutAfterReturning" expression=
"execution(* org.baeldung.logger.SampleAdder+.*(..))"/>
<aop:after-returning method="afterReturn"
returning="returnValue" pointcut-ref="pointCutAfterReturning"/>
</aop:aspect>
</aop:config>
如你所见,定义了一个名为 simpleAdder
的简单 Bean,它代表了一个业务对象实例。此外,还创建了一个名为 AdderAfterReturnAspect
的 Aspect
实例。
当然,XML 并不是唯一的选择;如前所述,AspectJ 注解也得到了完全支持。
4.7、配置概览 {#47配置概览}
使用 aop:config
标签来定义与 AOP 相关的配置。在 config
标签内部,定义表示切面的类。然后,为其提供一个引用 doAfterReturningAspect
,这是我们创建的一个切面 Bean。
接下来,使用 pointcut
标签定义一个 Pointcut
。上面示例中使用的 pointcut
是 execution(* org.baeldung.logger.SampleAdder+.*(..))
,这意味着对 SampleAdder
类中接受任意数量参数并返回任意值类型的任意方法应用 Advice(通知)。
然后,定义要应用的通知(Advice)。在上面的示例中,应用了后置返回通知(after-returning advice)。在切面 AdderAfterReturnAspect
中通过使用 method
属性执行我们定义的 afterReturn
方法来定义此通知。
切面中的通知(Advice)接受一个类型为 Object
的参数。该参数提供了在目标方法调用之前/之后执行操作的机会。在本例中,我们只是记录了方法的返回值。
Spring AOP 支持使用基于注解的配置的多种类型的通知(Advice)。你可以在 Spring 中文档 找到更多的示例。
5、总结 {#5总结}
本文介绍了 AOP 中的概念,还通过实际例子介绍了如何使用 Spring AOP。
Ref:https://www.baeldung.com/spring-aop