第一步
在切面类上面加上注解
@Aspect @Component
第二步
配置切点表达式
说明:切入点表达式决定了哪些类和方法将被增强。Spring AOP使用AspectJ切入点表达式语言来指定切入点。
1.方法执行(execution):
最常用的切入点指示器,可以匹配方法执行的连接点。
示例:匹配任何返回类型的 transfer
方法
@Pointcut("execution(* transfer(..))") public void anyTransfer() {}
2.方法注解(@annotation)
匹配任何被指定注解标记的方法。
示例:匹配所有被 @Transactional
注解的方法
@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)") public void transactionalMethods() {}
3.类注解(@within)
匹配任何在指定类型内的方法。
示例:匹配所有在被 @RestController
注解的类中的方法
@Pointcut("@within(org.springframework.web.bind.annotation.RestController)") public void restControllerMethods() {}
4.Bean名称(bean)
匹配Spring应用上下文中指定名称的Bean的所有方法。
示例:匹配名称以 service
结尾的所有Bean
@Pointcut("bean(*service)") public void beanEndingWithService() {}
组合切入点
你可以使用逻辑运算符(&&、||、!)组合多个切入点表达式,创建更复杂的切入点。
示例:匹配所有在 service
包下或者所有使用了 @Transactional
注解的方法
@Pointcut("execution(* com.example.service.*.*(..)) || @annotation(org.springframework.transaction.annotation.Transactional)") public void serviceLayerExecutionOrTransactionalMethods() {}
参数传递
在Spring AOP中,你可以通过切入点表达式捕获方法执行时的参数,并将这些参数传递给增强(advice)方法。这允许你根据方法的输入参数来定制增强的行为。
1.在切入点表达式中指定参数
首先,在定义切入点表达式时,你需要指定哪些参数将被捕获。这可以通过使用args()
、@args()
、@annotation()
等表达式完成。args()
用于捕获传递给方法的参数,而@annotation()
用于捕获方法注解上的属性值。
示例:捕获方法参数
假设我们有一个记录用户活动的需求,我们想要在用户执行某些操作时捕获用户ID和操作详情。
@Pointcut("execution(* com.example.service.*.*(..)) && args(userId,..)") public void userActivity(Long userId) {}
这个切入点表达式匹配com.example.service
包下的所有方法,且这些方法的第一个参数是userId
。
2. 在增强(Advice)方法中接收参数
在增强方法中,你可以声明与切入点表达式中相同的参数。Spring AOP会自动将捕获的参数值传递给这些参数。
示例:使用捕获的参数
以下是一个@Before
增强,它在目标方法执行前运行,并利用捕获的userId
参数:
@Before("userActivity(userId)") public void logUserActivity(JoinPoint joinPoint, Long userId) { String methodName = joinPoint.getSignature().getName(); System.out.println("User with ID " + userId + " is about to execute " + methodName); }
示例:捕获方法注解属性
如果你想要基于方法注解的某个属性来定制增强行为,可以使用@annotation()
来捕获注解实例。
假设我们有一个@Loggable
注解,其中包含一个用于描述日志级别的属性。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Loggable { LogLevel level() default LogLevel.INFO; }
你可以定义一个切入点来捕获这个注解及其属性:
@Pointcut("@annotation(loggable)") public void loggableMethod(Loggable loggable) {}
然后,在增强方法中使用这个注解:
@Before("loggableMethod(loggable)") public void logExecution(JoinPoint joinPoint, Loggable loggable) { System.out.println("Executing method: " + joinPoint.getSignature().getName() + " with log level: " + loggable.level()); }
这样,每当执行被@Loggable
注解的方法时,你都可以根据注解中指定的日志级别来执行日志记录逻辑。
第三步
在需要增加的方法上加上注解,或者根据规律写出切点表达式