非常棒 👍 阿杰!
Spring AOP 是 Spring 框架的核心之一,经常在日志、权限验证、事务管理、性能监控等功能中使用。

下面我给你一份超详细又实用的 Spring AOP 全面讲解,从概念到底层实现全覆盖,让你彻底搞懂它 👇


🌟 一、什么是 AOP?

AOP(Aspect-Oriented Programming)
中文叫 面向切面编程

它的目标是:

在不改变业务代码的前提下,统一地对系统功能进行增强。


🧩 举个例子:

假设你有很多业务方法:

public void addUser() { ... }
public void deleteUser() { ... }
public void updateUser() { ... }

如果每个方法前都要打印日志、检查权限、开启事务……
那你就得在每个方法里写重复代码 👇

System.out.println("开始执行...");
checkPermission();

这时候,AOP 出场了。
你只需要定义一个切面(Aspect),告诉 Spring:
“在这些方法执行前,帮我自动加上日志逻辑”。


⚙️ 二、AOP 的核心概念

概念说明
切面(Aspect)横切逻辑模块(比如日志、事务、权限)
连接点(JoinPoint)程序中可以被 AOP 拦截的点(方法调用、异常抛出等)
切入点(Pointcut)实际要被拦截的具体连接点表达式(匹配规则)
通知(Advice)在连接点执行的具体动作(前置、后置、环绕等)
目标对象(Target)被增强的业务类
代理对象(Proxy)由 Spring AOP 动态创建,用于包装目标对象
织入(Weaving)把切面逻辑应用到目标对象的过程(运行时完成)

🧠 三、AOP 的底层原理

Spring AOP 使用两种代理机制:

代理方式触发条件底层实现
JDK 动态代理目标对象实现了接口java.lang.reflect.Proxy
CGLIB 动态代理目标对象没有实现接口通过继承目标类、生成子类

✅ Spring Boot 默认自动选择合适的代理方式。


🧱 四、Spring AOP 快速示例

1️⃣ 添加依赖(Spring Boot 已自带)

如果是独立 Spring 项目,需要添加:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>


2️⃣ 定义一个业务类

package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void addUser(String name) {
        System.out.println("业务逻辑:添加用户 " + name);
    }
}


3️⃣ 定义一个切面类(Aspect)

package com.example.aspect;

import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAspect {

    // 切入点:指定匹配的目标方法(包名 + 类 + 方法)
    @Pointcut("execution(* com.example.service.UserService.*(..))")
    public void userServiceMethods() {}

    // 前置通知
    @Before("userServiceMethods()")
    public void before() {
        System.out.println("🟢 [Before] 方法执行前记录日志");
    }

    // 后置通知(无论异常与否都会执行)
    @After("userServiceMethods()")
    public void after() {
        System.out.println("🔵 [After] 方法执行结束");
    }

    // 返回后通知
    @AfterReturning("userServiceMethods()")
    public void afterReturning() {
        System.out.println("✅ [AfterReturning] 方法正常返回");
    }

    // 异常通知
    @AfterThrowing("userServiceMethods()")
    public void afterThrowing() {
        System.out.println("❌ [AfterThrowing] 方法抛出异常");
    }

    // 环绕通知(最强大,可以完全控制方法调用)
    @Around("userServiceMethods()")
    public Object around(org.aspectj.lang.ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("⚙️ [Around-Before] 环绕前逻辑");
        Object result = pjp.proceed(); // 执行目标方法
        System.out.println("⚙️ [Around-After] 环绕后逻辑");
        return result;
    }
}


4️⃣ 启动类(确保 AOP 生效)

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy  // 启用 AOP 代理功能
public class AopDemoApplication {
    public static void main(String[] args) {
        var context = SpringApplication.run(AopDemoApplication.class, args);
        var userService = context.getBean("userService", com.example.service.UserService.class);
        userService.addUser("阿杰");
    }
}


5️⃣ 控制台输出结果

🟢 [Before] 方法执行前记录日志
⚙️ [Around-Before] 环绕前逻辑
业务逻辑:添加用户 阿杰
⚙️ [Around-After] 环绕后逻辑
✅ [AfterReturning] 方法正常返回
🔵 [After] 方法执行结束

🚀 你会发现,AOP 自动帮你在目标方法前后插入了逻辑,而你完全没改业务代码!


🧩 五、常见切入点表达式

表达式说明
execution(* com.example.service.*.*(..))匹配 service 包下所有方法
execution(* com.example..*(..))匹配 com.example 包及子包下所有方法
@annotation(org.springframework.transaction.annotation.Transactional)匹配带 @Transactional 注解的方法
within(com.example.controller..*)匹配某个包内所有类的方法
args(String, ..)匹配第一个参数为 String 的方法

🧰 六、五种通知类型对比

通知类型注解触发时机是否能阻止执行
前置通知@Before方法执行前
后置通知@After方法执行后(无论异常)
返回通知@AfterReturning方法正常返回后
异常通知@AfterThrowing方法抛异常后
环绕通知@Around方法执行前后✅(可以决定是否继续执行)

⚡ 七、AOP 常见应用场景

场景示例
日志记录记录接口调用、方法耗时
权限验证判断当前用户是否有访问权限
事务管理@Transactional 就是 AOP 实现的
缓存管理缓存读取 / 更新拦截
性能监控统计接口耗时
异常处理全局捕获统一格式输出

🔍 八、Spring AOP vs AspectJ

对比项Spring AOPAspectJ
实现方式动态代理(运行时织入)编译期或类加载期织入
性能略低更高
使用复杂度简单(Spring Boot 开箱即用)较复杂
应用场景业务级增强系统级增强(如编译期检查)

Spring AOP 默认使用 AspectJ 的注解语法,但不需要 AspectJ 编译器


🧭 九、总结速查表

概念英文名简述
切面Aspect封装横切逻辑的类
通知Advice具体执行逻辑(前置、后置等)
切入点Pointcut定义哪些方法要被拦截
连接点JoinPoint程序执行的具体点
织入Weaving将切面逻辑应用到目标对象
代理对象Proxy被增强的对象
常用注解@Aspect, @Before, @Around
启用注解@EnableAspectJAutoProxy

🧠 十、扩展建议

你可以练习做一个实用项目,比如:

✅ “AOP 日志监控系统”

功能:

  • 拦截所有 @RestController 的接口;
  • 打印方法名、参数、执行时间、返回值;
  • @Around 实现;
  • 自动写入日志文件。

是否希望我帮你写出这个 AOP 接口调用日志监控系统(含完整代码 + 输出示例)
能直接复制进你的 Spring Boot 项目运行。