🔪 AOP 切面编程

Aspect Oriented Programming - 面向切面编程

📚 核心概念

AOP (面向切面编程):将横切关注点(日志、权限、事务等)从业务逻辑中分离出来,实现模块化。

目标方法
@Before
@Around (前)
方法执行
@Around (后)
@AfterReturning
@After

🔔 五种通知类型

@Before - 前置通知

方法执行前触发,可用于参数校验、日志记录

@Before("execution(* com.example.service..*.*(..))")
public void before(JoinPoint jp) {
log.info("即将执行: " + jp.getSignature().getName());
}

@After - 后置通知

方法执行后触发(无论是否异常),可用于资源释放

@After("execution(* com.example.service..*.*(..))")
public void after(JoinPoint jp) {
log.info("执行完成: " + jp.getSignature().getName());
}

@AfterReturning - 返回通知

方法成功返回后触发,可获取返回值

@AfterReturning(pointcut="...", returning="result")
public void afterReturning(Object result) {
log.info("返回结果: " + result);
}

@AfterThrowing - 异常通知

方法抛出异常后触发,可用于异常处理

@AfterThrowing(pointcut="...", throwing="ex")
public void afterThrowing(Exception ex) {
log.error("发生异常: " + ex.getMessage());
}

@Around - 环绕通知

完全控制方法执行,可决定是否执行目标方法

@Around("execution(* com.example.controller..*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed(); // 执行目标方法
long cost = System.currentTimeMillis() - start;
log.info("耗时: " + cost + "ms");
return result;
}

🧪 在线测试

调用下面的 API,然后查看控制台日志观察 AOP 执行顺序

📝 切入点表达式

表达式含义
execution(* *(..))匹配所有方法
execution(* com.example.service.*.*(..))service包下所有方法
execution(* com.example.service..*.*(..))service包及子包所有方法
execution(public * *(..))所有public方法
@annotation(org.springframework.transaction.annotation.Transactional)带@Transactional的方法