1. 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 核心通知
package com.example.aspect;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Order(1)
@Component
public class RequestAspect {
@Pointcut("execution(* com.example.controller..*(..))")
public void pc() {
}
/**
* around通知必须有返回值
*/
@SneakyThrows
@Around("com.example.aspect.RequestAspect.pc()")
public Object around(ProceedingJoinPoint joinPoint) {
System.out.println("around start");
Object result = joinPoint.proceed();
System.out.println("around end");
return result;
}
@Before("pc()")
public void before() {
System.out.println("before");
}
@After("pc()")
public void after() {
System.out.println("after");
}
@AfterReturning("pc()")
public void afterReturning() {
System.out.println("afterReturning");
}
@AfterThrowing("pc()")
public void afterThrowing() {
System.out.println("afterThrowing");
}
}
around start
before
@RequestMapping
afterReturning
after
around end
3. 执行顺序
@Around joinPoint.proceed()
@Before @RequestMapping @AfterReturning/@AfterThrowing @After
(目标方法抛出异常,@After后跳出切面往上抛,不会再回到@Around)
@Around
4. 切点表达式
4.1 execution方法签名匹配
返回类型和异常可以省略。
execution(<访问修饰符> <返回类型> <包名.类名.⽅法(⽅法参数)> <异常>)
@Pointcut("execution(* com.example.controller..*(..))")
4.2 @annotation注解匹配
@annotation(注解路径)
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
4.3 @Pointcut切点表达式
@Pointcut可以定义公共切点表达式,也可以在其他切面类中使用。
@Around("com.example.aspect.RequestAspect.pc()")
5. 动态代理
Spring Boot 中的AOP,2.0之前和Spring一样,2.0之后默认使用CGLIB动态代理。
JDK动态代理是模拟接口实现的方式,CGLIB是模拟子类继承的方式。
如果要使用JDK代理,需要在application.yml中增加如下配置。
spring:
aop:
proxy-target-class: false