一、AOP是什么?一句话就能懂!
AOP(面向切面编程),就是把每个方法都要写的重复代码(比如日志、权限校验)抽出来,统一管理的技术。举个例子:
假设你写了100个方法,每个方法都要记录日志,传统写法要写100遍日志代码,而AOP只需要写1次,自动应用到所有方法!
二、AOP最核心的三个概念(小白也能懂)
1. 切面(Aspect)
作用:用来装“重复代码”的容器,比如日志切面、权限切面。
代码示例(日志切面举例):
@Aspect // 声明这是一个切面
@Component // 让Spring管理这个类
public class LogAspect {
// 这里写具体的日志处理逻辑
}
2. 切点(Pointcut)
作用:告诉Spring“要对哪些方法生效”,用表达式定位方法。
// 示例:拦截所有Service层的方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
3. 通知(Advice)
作用:定义“什么时候执行重复代码”,比如方法执行前、执行后、环绕通知等。
- @Before:方法执行前(适合权限校验)
- @After:方法执行后(无论成功或失败)
- @Around:方法执行前后都处理(适合记录耗时)
三、一个案例学会AOP(日志实战)
场景:给所有Controller方法添加请求耗时日志
步骤1:定义切面
@Aspect
@Component
public class TimeLogAspect {
// 拦截所有Controller的方法
@Around("execution(* com.example.controller.*.*(..))")
public Object logTime(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
// 执行原方法
Object result = pjp.proceed();
long cost = System.currentTimeMillis() - start;
System.out.println(pjp.getSignature().getName() + "方法耗时:" + cost + "ms");
return result;
}
}
步骤2:调用效果
@RestController
public class UserController {
@GetMapping("/user")
public List getUsers() {
// 业务代码...
}
}
控制台输出:
getUsers方法耗时:48ms
四、AOP底层原理(通俗版)
动态代理:让代码“分身”的魔法
- JDK动态代理:如果目标类有接口,Spring会生成一个接口的代理类,通过反射调用方法。
- CGLIB代理:如果目标类没有接口,Spring会生成一个子类代理,覆盖父类方法。
举个栗子:
假设你有一个UserService类:
public class UserService {
public void saveUser() { ... }
}
Spring会在运行时生成一个代理类(伪代码):
public class UserServiceProxy extends UserService {
@Override
public void saveUser() {
// 执行AOP逻辑(如日志)
super.saveUser(); // 调用原方法
// 执行AOP逻辑(如记录耗时)
}
}
五、AOP的三大经典应用场景
场景 | 实现方式 | 优势 |
统一日志 | @Around记录方法耗时 | 一键监控所有接口性能 |
权限校验 | @Before + 自定义注解 | 避免每个方法写重复代码 |
事务管理 | @Around + 提交/回滚事务 | 保证数据库操作一致性 |
六、避坑指南(真实开发经验)
问题1:AOP不生效?
- 检查1:切面类是否加了@Component或@Aspect注解?
- 检查2:切点表达式是否写错了?比如包名拼写错误。
- 检查3:方法是否是public?AOP默认只拦截public方法。
问题2:事务失效?
- 原因:Spring默认使用JDK动态代理,如果目标类没有接口,需强制使用CGLIB:
# application.properties
spring.aop.proxy-target-class=true
七、AOP常见问题解答
Q1:AOP和拦截器(Interceptor)有什么区别?
- AOP:作用于方法级别,可精细控制(如只拦截Service层)。
- 拦截器:作用于请求级别,适合全局处理(如登录验证)。
Q2:如何选择@Around和@Before/@After?
- 用@Around:需要控制方法执行时机(比如计算耗时、事务管理)。
- 用@Before/@After:只需在方法前后执行简单操作(如参数校验)。
八、结语:AOP到底有多实用?
当你发现项目中到处都是重复的日志、权限代码时,AOP就是你的“代码瘦身教练”!本文代码可直接复制到Spring Boot项目中使用,关注我,下期手把手教你用AOP实现接口限流,彻底告别代码冗余!