顾乔芝士网

持续更新的前后端开发技术栈

Spring AOP保姆级教程!5分钟上手,彻底解决重复代码!

一、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实现接口限流,彻底告别代码冗余!

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言