📜  Spring AOP-基于建议的XML(1)

📅  最后修改于: 2023-12-03 15:35:02.842000             🧑  作者: Mango

Spring AOP-基于建议的XML

Spring AOP是Spring框架中非常重要的一个模块,它提供了基于建议的编程方式,可以很好地实现横向切面关注点(cross-cutting concerns)的处理,比如事务管理、安全性校验、缓存、日志等等。在这篇文章中,我们将通过一个XML配置的示例,介绍Spring AOP模块的基本使用。

依赖

在开始之前,我们需要在程序中添加Spring AOP的依赖。如果你使用的是Maven或Gradle,可以按照下面的依赖添加到你的pom.xml或build.gradle中。

<!-- Maven -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
</dependency>

<!-- Gradle -->
compile 'org.springframework:spring-aop:${spring.version}'
配置

为了使用Spring AOP,我们需要在 Spring 配置文件(如 applicationContext.xml)中进行以下配置:

开启AOP

使用 aop:aspectj-autoproxy 标签来启用 AspectJ 自动代理。该标签会在运行时使用 AspectJ 创建代理类,代理被 @Aspect 注解的类。

<aop:aspectj-autoproxy />
配置切面

使用 aop:config 标签开启切面配置。同时我们需要在 config 里定义一个 aop:aspect 标签来声明一个切面。通过 ref 属性指定切面绑定的切面类。

<aop:config>
    <aop:aspect ref="myAspect">
        ...
    </aop:aspect>
<aop:config>
配置切点

使用 aop:pointcut 标签来声明切点,它定义了一个连接点表达式(Pointcut Expression),该表达式指定了哪些方法需要被拦截。

<aop:pointcut id="businessService" expression="execution(* com.example.service.*.*(..))" />

上面的 expression 的含义是,拦截 com.example.service 包下的所有方法。

配置通知

使用 aop:advisor 标签来配置通知,pointcut-ref 属性用于引用之前定义的切点。在通知中定义了哪些行为需要在执行目标方法前或后执行。

<aop:advisor advice-ref="myAdvice" pointcut-ref="businessService" />
示例

现在我们要实现一个记录请求耗时的功能,以此来说明Spring AOP的使用。

  • 定义切面类 MyAspect
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
    @Around("execution(* com.example.controller.*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long totalTime = System.currentTimeMillis() - startTime;
        System.out.println(String.format("%s 耗时 %d ms", joinPoint.getSignature(), totalTime));
        return proceed;
    }
}

这个切面类 MyAspect 注解标注了 @Aspect,指定它是一个切面类。同时在类中声明了一个公共方法 logExecutionTime,这个方法使用了 @Around 注解,表示它是一个环绕通知。环绕通知会在目标方法执行前后都执行,这里我们使用 ProceedingJoinPoint 来捕捉目标方法,调用 proceed() 后才会执行目标方法。

在方法中,我们记录了请求开始时间,然后调用 proceed() 执行目标方法,接着计算总耗时,并将日志输出到控制台。

  • 配置 applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 开启AOP -->
    <aop:aspectj-autoproxy />

    <!-- 声明切面 -->
    <bean id="myAspect" class="com.example.aspect.MyAspect" />

    <!-- 声明切点 -->
    <aop:pointcut id="controllerMethods" expression="execution(* com.example.controller.*.*(..))" />

    <!-- 配置通知 -->
    <aop:advisor advice-ref="myAspect" pointcut-ref="controllerMethods" />
</beans>

这个 applicationContext.xml 配置文件中包含了上述的三个配置部分,并通过 bean 标签声明了 MyAspect,然后使用 aop:pointcut 声明了切点 controllerMethods,它包含了 com.example.controller 包下所有方法。最后使用 aop:advisor 配置了 myAspect,在切点 controllerMethods 上生效。

总结

通过上述示例和解释,我们学习了Spring AOP的基本使用和配置。AOP可以帮助我们解决许多问题(如对日志、监控、缓存、事务等的封装),使代码具备更好的可重用性和可维护性。