Spring AOP 参数绑定:从 0 到会(一页就懂版)😄
适用人群:
- 知道 Spring AOP 是啥
- 写过
@Around / @Before- 但对「注解是怎么传进 Advice 的」有点懵
这篇文章不默认你已经懂,我们从「注解怎么写」开始。
0️⃣ 先准备一个“被切的注解”(否则一切都是空谈)
1 |
|
关键点(只记 2 个):
@Retention(RUNTIME):没这个,AOP 在运行时根本拿不到注解
METHOD / TYPE:决定你后面能不能用
@annotation/@within
1️⃣ 再看一个“被切的方法”(完整上下文)
1 |
|
现在场景明确了:
- 方法上有
@Auth - AOP 想在运行时 拿到这个注解里的配置
2️⃣ 最容易让人懵的地方:两种“几乎一样”的写法
❌ 写法一:只能“切到”,拿不到注解
1 |
|
它的真实含义是:
只要方法上“存在”
@Auth,我就切
✔ 能切
❌ 但你拿不到 @Auth 实例
原因很简单:
你只是问了“有没有”,
没说“拿给我”。
✅ 写法二:切 + 绑定 + 传参(正确姿势)
1 |
|
这里发生了三件事:
@annotation(auth)- auth 是变量名,不是类型
Spring 从目标方法上
- 拿到
@Auth注解实例
- 拿到
注入到参数
Auth auth
👉 这一步,叫 参数绑定(binding)
3️⃣ 一个万能记忆口诀(真的有用)
切点里写“类型” → 只判断有没有
切点里写“变量名” → 才能把值传进来
| 写法 | 含义 |
|---|---|
@annotation(Auth) |
存在性判断 |
@annotation(auth) |
绑定注解实例 |
args(id) |
绑定方法参数 |
target(service) |
绑定目标对象 |
4️⃣ 进阶:方法注解 + 类注解一起用怎么办?(千万别踩坑)
这是 AOP 的 真·进阶区。
先给结论(重点):
同一个注解同时出现在「方法」和「类」上时,Spring AOP 不会自动帮你选“谁优先”。
你必须在切面里自己定规则。也就是说——“优先级不是注解决定的,是你代码决定的。”
❌ 错误的依赖(不要赌)
1 |
|
✅ 正确姿势:你自己决定谁优先(标准写法)
业界共识规则(强烈推荐):方法级注解 > 类级注解。
这和 Spring Security、事务传播规则是一致的。
写法思路:
- 切面只负责“兜底捕获”(我是雷达,发现目标)。
- 代码负责“解析优先级”(我是指挥官,决定打谁)。
第一步:切面只“兜底”
1 | // 只负责命中,不负责绑定具体参数,避免歧义 |
第二步:自己解析优先级(核心)
1 | private Auth resolveAuth(ProceedingJoinPoint pjp) { |
🎯 为什么要这么麻烦?
这个方案的优点非常重要:
- ✔ 行为确定:不再依赖 Spring 的内部匹配顺序。
- ✔ 规则显式:新人看代码一眼就知道“方法优先”。
- ✔ 可扩展:如果你以后想支持 disable / inherit / merge 策略,改
resolveAuth就行,切面不用动。
💡 工程师级总结
@within / @annotation是 雷达:告诉你“都在”。resolveAuth才是 指挥官:告诉你“先打谁”。
5️⃣ 常见误区(90% 的坑都在这)
❌ 误区 1:Pointcut 参数 = 普通方法参数
实际:它是上下文占位符
❌ 误区 2:Advice 里多写一个参数,Spring 会自动给
实际:没绑定来源,直接启动报错
❌ 误区 3:Auth 和 auth 没区别
实际:
Auth:类型判断auth:变量绑定
6️⃣ 最后一段人话总结
AOP 参数不是“注入”的,
是你在切点里“声明来源”,
Spring 再把上下文对象塞给你。
写对了是自动挡,
写错了是离合踩到底还挂不上档。
TL;DR(真·一句话)
切点里不绑定变量名,Advice 里就永远拿不到参数。
——完
Comments




