SpringBoot AOP切面编程精讲:实现方式、Spring区别及与自定义注解生产实战

文章目录

一、AOP核心简介

AOP(面向切面编程)是Spring两大核心之一,核心作用就是不改动业务代码,就能对方法做统一增强,实现业务逻辑与公共逻辑解耦。常用于统一日志、接口耗时统计、权限校验、事务管理、操作记录等场景。

核心四要素:切点 (要拦截哪些方法)、切面 (增强处理类)、通知 (前后/环绕/异常等增强逻辑)、连接点(被拦截的目标方法)。

二、SpringBoot快速实现AOP(注解版)

1. 引入核心依赖

SpringBoot无需繁琐配置,仅需引入AOP启动器,自动完成装配。

xml 复制代码
<!-- SpringBoot AOP核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 编写切面类(五种通知完整示例)

@Aspect标记切面类,@Component交给容器管理,通过切点匹配目标方法,配置不同通知完成增强。

java 复制代码
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAndTimeAspect {
    // 切点:拦截controller包下所有方法
    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    public void controllerPointCut(){}

    // 前置通知:方法执行前
    @Before("controllerPointCut()")
    public void beforeAdvice(){
        System.out.println("【前置通知】方法开始执行");
    }

    // 后置通知:无论是否异常,执行完毕都执行
    @After("controllerPointCut()")
    public void afterAdvice(){
        System.out.println("【后置通知】方法执行结束");
    }

    // 返回通知:方法正常返回后执行
    @AfterReturning(pointcut = "controllerPointCut()",returning = "result")
    public void afterReturningAdvice(Object result){
        System.out.println("【返回通知】返回值:" + result);
    }

    // 异常通知:方法报错时执行
    @AfterThrowing(pointcut = "controllerPointCut()",throwing = "e")
    public void afterThrowingAdvice(Exception e){
        System.out.println("【异常通知】异常信息:" + e.getMessage());
    }

    // 环绕通知:功能最强,手动控制方法执行前后逻辑
    @Around("controllerPointCut()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        // 执行目标方法
        Object result = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        System.out.println("【环绕通知】方法耗时:" + (endTime - startTime) + "ms");
        return result;
    }
}

3. 测试接口

java 复制代码
@RestController
public class AopTestController {
    @GetMapping("/aop/test")
    public String aopTest(){
        System.out.println("业务方法执行中");
        return "AOP执行成功";
    }
}

4. 通知执行顺序

正常执行:环绕前置 → 前置通知 → 目标方法 → 返回通知 → 后置通知 → 环绕后置

异常执行:环绕前置 → 前置通知 → 方法报错 → 异常通知 → 后置通知

三、传统Spring AOP vs SpringBoot AOP核心区别

两者底层原理、切点规则、通知逻辑完全一样,核心区别仅在配置和使用方式。

1. 核心差异汇总

  • 配置方式:Spring AOP必须写XML配置,繁琐冗余;SpringBoot AOP零XML,纯注解开箱即用。

  • 依赖管理:Spring需手动导入多个Jar、处理版本冲突;SpringBoot只需一个启动器,自动管控版本。

  • 代理开启:Spring需手动配置AOP自动代理标签;SpringBoot默认自动开启,无需手动配置。

  • 适用场景:Spring AOP仅用于老旧SSM项目维护;SpringBoot AOP是新项目、微服务标配。

四、SpringBoot AOP切面 vs 自定义注解(生产重点)

1. 核心关系

AOP切面 :干活的拦截器,负责方法增强逻辑;自定义注解:标记开关,只负责筛选哪些方法需要拦截。

两者不是二选一,生产标配:AOP切面 + 自定义注解组合使用

2. 两种方式对比

对比维度 纯AOP按包名拦截(execution) AOP+自定义注解(精准拦截)
拦截范围 全局批量拦截,范围大 只拦截加注解的方法,精准可控
误拦截风险 高,容易拦截无关方法 无,不加注解不生效
适用场景 全局耗时、基础统一日志 操作日志、权限、限流、数据脱敏
生产推荐 少用、不推荐 首选、企业标准

五、实战1:纯AOP全局拦截(仅演示,不推荐生产)

按包名一刀切,所有接口都拦截,无法单独控制,容易产生垃圾日志。

java 复制代码
@Aspect
@Component
public class AllApiLogAspect {
    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    public void pointcut(){}

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("接口入参:" + Arrays.toString(joinPoint.getArgs()));
        Object result = joinPoint.proceed();
        System.out.println("接口出参:" + result);
        return result;
    }
}

六、实战2:AOP+自定义注解(生产标准写法)

1. 创建自定义标记注解

java 复制代码
import java.lang.annotation.*;

// 仅标记方法、运行时生效
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperateLog {
    String value() default ""; // 记录操作描述
}

2. 切面拦截该注解

java 复制代码
@Aspect
@Component
public class OperateLogAspect {
    // 只拦截加了@OperateLog注解的方法
    @Pointcut("@annotation(com.example.demo.annotation.OperateLog)")
    public void operateLogPointcut(){}

    @Around("operateLogPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("===== 记录重要操作日志 =====");
        System.out.println("操作方法:" + joinPoint.getSignature().getName());
        System.out.println("请求参数:" + Arrays.toString(joinPoint.getArgs()));
        Object result = joinPoint.proceed();
        System.out.println("操作返回结果:" + result);
        return result;
    }
}

3. 业务接口按需使用

java 复制代码
@RestController
public class UserController {
    // 普通查询:不加注解 → 不记录日志
    @GetMapping("/user/get")
    public String getUser(){
        return "查询用户";
    }

    // 重要操作:加注解 → AOP自动记录日志
    @OperateLog("删除用户操作")
    @GetMapping("/user/delete")
    public String deleteUser(){
        return "删除成功";
    }
}

七、最终生产总结

  1. 简单全局通用功能,可少量使用纯AOP包名拦截;

  2. 业务特殊增强功能,一律使用AOP+自定义注解,精准可控、好维护;

  3. SpringBoot新项目只用注解AOP,传统Spring XML配置仅作老旧项目维护使用。

相关推荐
胡小禾1 小时前
企业内部文件处理方案
java
常利兵2 小时前
Spring Boot:别再重复造轮子,这些内置功能香麻了
java·spring boot·后端
咸鱼翻身小阿橙3 小时前
Qt QML调用C++注册类
java·c++·qt
逸Y 仙X3 小时前
文章二十一:ElasticSearch 词项查询与调度查询实战
java·大数据·数据库·elasticsearch·搜索引擎
Bechamz3 小时前
大数据开发学习Day25
java·大数据·学习
shaoming37763 小时前
检查系统硬件配置是否满足PyCharm最低要求
android·spring boot·mysql
ffqws_3 小时前
Spring Boot 接收前端请求的四种参数方式
前端·spring boot·后端
咖啡八杯4 小时前
GoF设计模式——单例模式
java