Spring AOP 核心知识点详解笔记
一、AOP 基础概念与核心组件
核心思想
AOP(面向切面编程)是一种通过预编译或运行时动态代理实现横切关注点(Cross-Cutting Concerns)模块化的编程范式。其核心目标是:
解耦:将与业务无关的代码(如日志、权限)从核心逻辑中剥离
可维护性:集中管理横切逻辑,避免散落在各业务模块
灵活性:通过配置快速启用/禁用功能模块,无需修改源码
核心术语
术语 | 描述 | 示例 |
---|---|---|
切面(Aspect) | 横切关注点的模块化实现,包含通知和切入点定义 | 日志切面、权限切面 |
连接点(Join Point) | 程序执行过程中的特定节点(如方法调用、异常抛出) | UserService.getUser() 方法执行 |
切入点(Pointcut) | 通过表达式定义需要拦截的连接点集合 | execution(* com.example.service.*.*(..)) |
通知(Advice) | 在切入点执行的增强逻辑,分为五类: @Before/@After/@Around/@AfterReturning/@AfterThrowing |
记录方法耗时、异常报警 |
织入(Weaving) | 将切面逻辑插入目标对象的过程,Spring AOP 采用动态代理实现 | JDK动态代理(接口)或CGLIB代理(类) |
关键特性
Spring AOP 属于运行时增强,仅支持方法级别的连接点(不支持字段/构造器)
二、Spring Boot 集成实践
基础配置步骤
添加依赖
1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
该依赖已包含 AspectJ 注解支持,无需额外配置
启用自动代理
通过 @EnableAspectJAutoProxy
开启(Spring Boot 默认自动配置)
定义切面类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 控制切面执行顺序
public class LoggingAspect {
public void serviceLayer() {}
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
log.info("Method {} executed in {} ms",
joinPoint.getSignature(),
System.currentTimeMillis() start);
return result;
}
}
代码说明
@Aspect
标识切面类,@Component
使其被 Spring 管理@Order
控制多个切面的执行顺序(值越小优先级越高)
切入点表达式类型
表达式类型 | 示例 | 适用场景 |
---|---|---|
execution | execution(* com.service.*.*(..)) |
匹配方法执行 |
within | within(com.controller..*) |
匹配包/类内所有方法 |
@annotation | @annotation(com.example.Log) |
匹配带有特定注解的方法 |
args | args(java.lang.String, ..) |
匹配参数类型 |
三、典型应用场景深度解析
统一日志管理
实现方式:
使用 @Around
记录方法耗时
通过 JoinPoint
获取方法签名、参数
结合 SLF4J 输出结构化日志
代码示例:
1 |
|
技术要点
使用RequestContextHolder
在非 Controller 层获取请求对象
权限控制
实现方式:
自定义 @PreAuthorize
注解
结合 Spring Security 的权限表达式
代码示例:
1 |
|
事务管理增强
实现方式:
通过 @Transactional
注解的环绕通知
实现多数据源动态切换(读写分离)
代码示例:
1 |
|
四、高级技巧与最佳实践
自定义注解增强
实现步骤:
定义注解:
1
2
3
4
5
public TimeMonitor {
String metricName() default "";
}
切面处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TimeMonitorAspect {
public Object monitorTime(ProceedingJoinPoint joinPoint, TimeMonitor monitor) throws Throwable {
long start = System.nanoTime();
Object result = joinPoint.proceed();
long duration = System.nanoTime() start;
Metrics.record(monitor.metricName(), duration);
return result;
}
}
优势:通过注解声明式配置监控指标,避免硬编码
多切面执行顺序控制
控制方式 | 实现方法 |
---|---|
@Order 注解 | 类级别注解,数值越小优先级越高(如事务切面通常设为最高) |
实现 Ordered 接口 | 重写 getOrder() 方法返回优先级数值 |
异常处理增强
实现方式:
1 |
|
五、常见问题与解决方案
切面不生效排查
可能原因 | 解决方案 |
---|---|
Bean 未被 Spring 管理 | 检查切面类是否添加 @Component 或其他 Stereotype 注解 |
切入点表达式错误 | 使用 AopUtils 工具类调试匹配结果 |
代理模式限制 | CGLIB 代理需确保类和方法非 final |
性能优化建议
避免在切面中执行耗时操作(如远程调用)
使用条件化切入点减少匹配范围(如 @within
替代宽泛的 execution
)
对高频调用方法禁用非必要切面
六、扩展应用场景
分布式缓存管理
实现方案:
1 |
|
可结合 Redis、Ehcache 等实现
API 版本控制
实现方案:
1 |
|