1.概述
在 Spring Boot 中,@Aspect是一个用于实现面向切面编程(AOP - Aspect - Oriented Programming)的注解。AOP 是一种编程范式,它允许开发者将横切关注点(如日志记录、性能统计、事务管理等)从业务逻辑中分离出来,从而使代码更加模块化、可维护和可重用。@Aspect注解用于标记一个类,表明这个类是一个切面(Aspect)。
2.创建切面类
首先,需要创建一个带有@Aspect注解的 Java 类。例如:
java">import org. aspectj. lang. annotation. Aspect ;
import org. springframework. stereotype. Component ;
@Aspect
@Component
public class LoggingAspect {
}
这里的@Aspect注解表明LoggingAspect是一个切面类,@Component注解则是为了让 Spring能够扫描并管理这个切面类,将其作为一个 Spring 组件。
3.定义切点(Pointcut)
切点用于指定在哪些方法或类上应用切面逻辑。可以使用@Pointcut注解来定义切点。例如,以下是一个简单的切点定义,用于匹配某个包下的所有方法:
java">import org. aspectj. lang. annotation. Aspect ;
import org. aspectj. lang. annotation. Pointcut ;
import org. springframework. stereotype. Component ;
@Aspect
@Component
public class LoggingAspect {
@Pointcut ( "execution(* com.example.demo.service..*.*(..))" )
public void serviceMethods ( ) { }
}
在这个例子中,@Pointcut注解中的表达式execution(* com.example.demo.service…. (…))是一个切点表达式。它表示匹配com.example.demo.service包及其子包下的所有类的所有方法,无论方法的返回值类型和参数列表如何。
4.定义通知(Advice)
通知是切面中的具体逻辑,用于在切点所匹配的方法执行前后或出现异常时执行特定的操作。有以下几种类型的通知: 前置通知 前置通知(Before):在目标方法执行之前执行的通知。可以使用@Before注解来定义前置通知。例如:
java">import org. aspectj. lang. annotation. Aspect ;
import org. aspectj. lang. annotation. Before ;
import org. aspectj. lang. annotation. Pointcut ;
import org. springframework. stereotype. Component ;
@Aspect
@Component
public class LoggingAspect {
@Pointcut ( "execution(* com.example.demo.service..*.*(..))" )
public void serviceMethods ( ) { }
@Before ( "serviceMethods()" )
public void logBeforeServiceMethod ( ) {
System . out. println ( "在服务方法执行之前记录日志" ) ;
}
}
在这个例子中,@Before(“serviceMethods()”)表示在serviceMethods切点所匹配的方法执行之前,会执行logBeforeServiceMethod方法,这里只是简单地打印了一条日志。 后置通知 后置通知(After):在目标方法执行之后执行的通知。使用@After注解定义,如下:
java">import org. aspectj. lang. annotation. After ;
import org. aspectj. lang. annotation. Aspect ;
import org. aspectj. lang. annotation. Pointcut ;
import org. springframework. stereotype. Component ;
@Aspect
@Component
public class LoggingAspect {
@Pointcut ( "execution(* com.example.demo.service..*.*(..))" )
public void serviceMethods ( ) { }
@After ( "serviceMethods()" )
public void logAfterServiceMethod ( ) {
System . out. println ( "在服务方法执行之后记录日志" ) ;
}
}
返回通知 返回通知(AfterReturning):在目标方法正常返回之后执行的通知。使用@AfterReturning注解定义,并且可以获取目标方法的返回值。例如:
java">import org. aspectj. lang. annotation. AfterReturning ;
import org. aspectj. lang. annotation. Aspect ;
import org. aspectj. lang. annotation. Pointcut ;
import org. springframework. stereotype. Component ;
@Aspect
@Component
public class LoggingAspect {
@Pointcut ( "execution(* com.example.demo.service..*.*(..))" )
public void serviceMethods ( ) { }
@AfterReturning ( pointcut = "serviceMethods()" , returning = "result" )
public void logAfterReturningServiceMethod ( Object result) {
System . out. println ( "服务方法返回值为: " + result) ;
}
}
异常通知 异常通知(AfterThrowing):在目标方法抛出异常时执行的通知。使用@AfterThrowing注解定义,可以获取抛出的异常对象。例如:
java">import org. aspectj. lang. annotation. AfterThrowing ;
import org. aspectj. lang. annotation. Aspect ;
import org. aspectj. lang. annotation. Pointcut ;
import org. springframework. stereotype. Component ;
@Aspect
@Component
public class LoggingAspect {
@Pointcut ( "execution(* com.example.demo.service..*.*(..))" )
public void serviceMethods ( ) { }
@AfterThrowing ( pointcut = "serviceMethods()" , throwing = "ex" )
public void logAfterThrowingServiceMethod ( Exception ex) {
System . out. println ( "服务方法抛出异常: " + ex. getMessage ( ) ) ;
}
}
5.切面的执行顺序
当有多个切面应用于同一个方法时,它们的执行顺序可以通过@Order注解来控制。例如:
java">import org. aspectj. lang. annotation. Aspect ;
import org. springframework. core. annotation. Order ;
import org. springframework. stereotype. Component ;
@Aspect
@Component
@Order ( 1 )
public class LoggingAspect {
}
在这个例子中,@Order(1)表示这个切面的执行顺序为1。数字越小,执行顺序越靠前。如果没有指定@Order注解,切面的执行顺序是不确定的。