Spring AOP 参数绑定:从 0 到会(一页就懂版)😄

22 阅读2分钟

适用人群

  • 知道 Spring AOP 是啥
  • 写过 @Around / @Before
  • 但对「注解是怎么传进 Advice 的」有点懵

这篇文章不默认你已经懂,我们从「注解怎么写」开始。


0️⃣ 先准备一个“被切的注解”(否则一切都是空谈)


@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {

    String value() default "";

    boolean required() default true;
}

关键点(只记 2 个):

  • @Retention(RUNTIME)

    没这个,AOP 在运行时根本拿不到注解

  • METHOD / TYPE

    决定你后面能不能用 @annotation / @within


1️⃣ 再看一个“被切的方法”(完整上下文)


@Auth("admin")
public void createOrder() {
    // business logic
}

现在场景明确了:

  • 方法上有 @Auth
  • AOP 想在运行时 拿到这个注解里的配置

2️⃣ 最容易让人懵的地方:两种“几乎一样”的写法

❌ 写法一:只能“切到”,拿不到注解


@Around("@annotation(Auth)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    return pjp.proceed();
}

它的真实含义是:

只要方法上“存在” @Auth,我就切

✔ 能切 ❌ 但你拿不到 @Auth 实例

原因很简单:

你只是问了“有没有”, 没说“拿给我”。


✅ 写法二:切 + 绑定 + 传参(正确姿势)


@Around("@annotation(auth)")
public Object around(ProceedingJoinPoint pjp, Auth auth) throws Throwable {
    // auth 就是方法上的 @Auth 注解实例
    String role = auth.value();
    return pjp.proceed();
}

这里发生了三件事:

  1. @annotation(auth)

    • auth 是变量名,不是类型
  2. Spring 从目标方法上

    • 拿到 @Auth 注解实例
  3. 注入到参数 Auth auth

👉 这一步,叫 参数绑定(binding)


3️⃣ 一个万能记忆口诀(真的有用)

切点里写“类型” → 只判断有没有 切点里写“变量名” → 才能把值传进来

写法含义
@annotation(Auth)存在性判断
@annotation(auth)绑定注解实例
args(id)绑定方法参数
target(service)绑定目标对象

4️⃣ 方法注解 + 类注解一起用怎么办?


@Around("@annotation(auth) || @within(auth)")
public Object around(ProceedingJoinPoint pjp, Auth auth) throws Throwable {
    return pjp.proceed();
}

含义是:

  • 方法上有 @Auth → 用方法级
  • 否则用类上的 @Auth

⚠️ 说明:

  • Spring 优先方法级
  • 但规则不直观

📌 权限 / 框架场景建议

手动解析更稳

Method m = ((MethodSignature) pjp.getSignature()).getMethod();
Auth auth = m.getAnnotation(Auth.class);
if(auth ==null){
auth =pjp.

getTarget().

getClass().

getAnnotation(Auth .class);
}

5️⃣ 常见误区(90% 的坑都在这)

❌ 误区 1:Pointcut 参数 = 普通方法参数

实际:它是上下文占位符

❌ 误区 2:Advice 里多写一个参数,Spring 会自动给

实际:没绑定来源,直接启动报错

❌ 误区 3:Authauth 没区别

实际:

  • Auth:类型判断
  • auth:变量绑定

6️⃣ 最后一段人话总结

AOP 参数不是“注入”的, 是你在切点里“声明来源”, Spring 再把上下文对象塞给你。

写对了是自动挡, 写错了是离合踩到底还挂不上档。


TL;DR(真·一句话)

切点里不绑定变量名,Advice 里就永远拿不到参数。

——完