# 🔪 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的方法