Spring AOP详解

目录


一、什么是 Spring AOP

AOP(Aspect-Oriented Programming,面向切面编程)
👉 本质:在不修改原有代码的情况下,给方法“动态增强功能”

一句话理解:

把“通用逻辑(日志、事务、权限)”从业务代码中抽离出来,统一管理。


二、为什么需要 AOP(解决什么问题)

2.1 痛点:代码重复 + 耦合高

比如你写业务:

1
2
3
4
5
public void save() {
log.info("开始");
// 业务逻辑
log.info("结束");
}

如果 100 个方法都要日志?

👉 ❌ 会变成:

  • 代码重复
  • 修改困难
  • 业务被污染

2.2 AOP 的解决思路

👉 把日志抽出来:

1
2
3
4
5
6
7
@Aspect
public class LogAspect {
@Before("execution(* com.xxx.service.*.*(..))")
public void before() {
log.info("方法开始");
}
}

👉 业务代码变干净:

1
2
3
public void save() {
// 只关注业务
}

三、AOP核心概念(面试必考🔥)

3.1 切面(Aspect)

👉 一个类,定义“增强逻辑”

1
2
@Aspect
public class LogAspect {}

3.2 切点(Pointcut)

👉 哪些方法需要被增强

1
execution(* com.xxx.service.*.*(..))

含义:

  • 任意返回值
  • service包
  • 任意类
  • 任意方法
  • 任意参数

3.3 通知(Advice)

👉 什么时候增强

类型 说明
@Before 方法执行前
@After 方法执行后
@AfterReturning 返回后
@AfterThrowing 异常后
@Around ⭐ 包裹整个方法

3.4 连接点(JoinPoint)

👉 可以被增强的方法(Spring中就是方法)

3.5 织入(Weaving)

👉 把“切面”应用到“目标对象”的过程

3.6 目标对象(Target)

👉 原始业务对象

3.7 代理对象(Proxy)⭐

👉 Spring AOP 本质是代理模式


四、Spring AOP底层原理(重点🔥🔥🔥)

Spring AOP不是编译时织入,而是:

👉 运行时基于代理实现

4.1 两种代理方式

(1)JDK动态代理

👉 条件:必须有接口

1
目标类实现了接口 → 用JDK代理

特点:

  • 基于接口
  • 生成代理类实现接口

(2)CGLIB代理

👉 条件:没有接口

1
目标类没有接口 → 用CGLIB

特点:

  • 继承目标类
  • 生成子类
  • 重写方法

4.2 代理选择机制

1
2
有接口 → JDK
无接口 → CGLIB

但可以强制:

1
2
3
spring:
aop:
proxy-target-class: true

👉 强制使用 CGLIB

4.3 执行流程(非常重要🔥)

调用:

1
userService.save();

实际执行:

1
2
3
4
5
6
7
代理对象.save()

执行 @Before

执行目标方法

执行 @After

👉 你调用的其实是代理对象,不是原对象


五、@Around 通知(面试高频🔥)

1
2
3
4
5
6
7
8
9
@Around("execution(* com.xxx.service.*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("前");

Object result = pjp.proceed(); // 执行目标方法

System.out.println("后");
return result;
}

📌 关键点:

  • proceed() 👉 决定是否执行目标方法

  • 可以:

    • 控制执行
    • 修改返回值
    • 做事务

六、Spring AOP的典型应用场景

1. 日志记录

2. 事务管理(最经典🔥)

👉 @Transactional 本质就是 AOP

3. 权限校验

4. 接口限流

5. 性能监控


七、常见面试坑(重点🔥)

❗1. AOP为什么不能拦截private方法?

👉 因为代理是基于方法重写(CGLIB)或接口实现(JDK)

→ private方法不能被重写 ❌

❗2. 自调用失效(超级高频🔥)

1
2
3
public void a() {
b(); // ❌ AOP失效
}

原因:

  • b()this调用
  • 没走代理对象

👉 解决:

1
2
3
4
@Autowired
private UserService self;

self.b(); // ✅

❗3. final方法不能增强

👉 因为不能被重写

❗4. Spring AOP vs AspectJ

对比 Spring AOP AspectJ
实现 运行时代理 编译期织入
性能 较低 更高
功能 方法级别 更强(字段、构造)

八、总结(面试回答模板🔥)

如果面试官问你:

👉 “讲一下Spring AOP”

你可以这样答:

Spring AOP 是基于代理模式实现的面向切面编程,用于将日志、事务等横切逻辑从业务代码中解耦。
它的核心概念包括切面、切点、通知等。
底层通过 JDK 动态代理或 CGLIB 在运行时生成代理对象,在方法执行前后织入增强逻辑。
常见应用包括事务管理、日志记录等。
需要注意自调用失效、private方法无法增强等问题。