当前位置: 首页 > news >正文

Spring AOP 中@annotation的两种写法详解

目录

  • 一、什么是 @annotation
  • 二、写法一:只拦截方法,不读取注解内容
  • 三、写法二:拦截 + 获取注解对象
  • 四、两种写法的对比总结
  • 五、完整运行示例
    • 1、自定义注解
    • 2、AOP 切面类
    • 3、被拦截的业务类
    • 4、输出结果
  • 六、总结

在 Spring AOP 的开发中,我们经常看到这样的切面写法:

@Before("@annotation(com.example.annotation.PayLog)")
public void beforeAnnotation() {System.out.println("通过 @annotation 拦截带 @PayLog 注解的方法");
}

或者这样:

@Before("@annotation(payLog)")
public void beforeAnnotation(PayLog payLog) {System.out.println("检测到支付操作:" + payLog.value());
}

看起来很相似,但又不太一样 🤔
到底有什么区别?为什么都能生效?
这篇文章帮你彻底搞清楚!


一、什么是 @annotation

在 AOP(Aspect-Oriented Programming,面向切面编程)中,
我们通过切点表达式定义要拦截的方法。

其中,@annotation(...) 是一种非常常见的表达式,用来匹配:

“所有带有指定注解的方法”。


举个例子

假设我们定义了一个自定义注解 @PayLog

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PayLog {String value() default "默认支付";
}

二、写法一:只拦截方法,不读取注解内容

@Aspect
@Component
public class PayAspect {@Before("@annotation(com.example.annotation.PayLog)")public void beforeAnnotation() {System.out.println("通过 @annotation 拦截带 @PayLog 注解的方法");}
}

这段切面表示:

“在执行任何带有 @PayLog 注解的方法之前,先执行我这个方法。”

示例:

@Service
public class OrderService {@PayLogpublic void pay() {System.out.println("执行支付逻辑...");}
}

输出:

通过 @annotation 拦截带 @PayLog 注解的方法
执行支付逻辑...

🧩 解释:

  • @annotation(com.example.annotation.PayLog) 表示拦截所有被该注解标记的方法;
  • beforeAnnotation() 方法执行时,并不会接收到注解对象;
  • 这种写法适合只想拦截,不需要读取注解里的内容。

三、写法二:拦截 + 获取注解对象

@Aspect
@Component
public class PayAspect {@Before("@annotation(payLog)")public void beforeAnnotation(PayLog payLog) {System.out.println("检测到支付操作:" + payLog.value());}
}

这段代码看起来只多了一个参数 payLog
其实功能更强大——它可以直接获取目标方法上的注解实例。


示例

@Service
public class OrderService {@PayLog("微信支付")public void payWx() {System.out.println("执行微信支付逻辑...");}@PayLog("支付宝支付")public void payAli() {System.out.println("执行支付宝支付逻辑...");}
}

输出结果:

检测到支付操作:微信支付
执行微信支付逻辑...
检测到支付操作:支付宝支付
执行支付宝支付逻辑...

🧠 解释:

  • @annotation(payLog) 告诉 AOP:
    拦截时把目标方法上的 @PayLog 实例赋值给 payLog 参数;
  • 于是我们可以直接通过 payLog.value() 获取注解中的值。

四、两种写法的对比总结

对比项写法一写法二
表达式@annotation(com.example.annotation.PayLog)@annotation(payLog)
方法参数有(注解类型参数)
是否能读取注解内容❌ 否✅ 可以
主要用途只做拦截、执行前后逻辑需要读取注解参数(如描述、类型等)
示例应用简单记录日志根据注解参数执行不同逻辑

五、完整运行示例

1、自定义注解

package com.example.annotation;import java.lang.annotation.*;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PayLog {String value() default "默认支付类型";
}

2、AOP 切面类

package com.example.aspect;import com.example.annotation.PayLog;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class PayAspect {// 写法一:只拦截@Before("@annotation(com.example.annotation.PayLog)")public void onlyIntercept() {System.out.println("拦截到带 @PayLog 注解的方法");}// 写法二:拦截 + 获取注解@Before("@annotation(payLog)")public void beforeWithAnnotation(PayLog payLog) {System.out.println("检测到支付操作:" + payLog.value());}
}

3、被拦截的业务类

package com.example.service;import com.example.annotation.PayLog;
import org.springframework.stereotype.Service;@Service
public class OrderService {@PayLog("微信支付")public void payWx() {System.out.println("执行微信支付逻辑...");}@PayLog("支付宝支付")public void payAli() {System.out.println("执行支付宝支付逻辑...");}
}

4、输出结果

拦截到带 @PayLog 注解的方法
检测到支付操作:微信支付
执行微信支付逻辑...拦截到带 @PayLog 注解的方法
检测到支付操作:支付宝支付
执行支付宝支付逻辑...

六、总结

@annotation 有两种写法:

  • @annotation(注解类路径):只拦截,不读参数;
  • @annotation(变量名) + 方法参数:拦截并获取注解对象。

两者都对,只是用途不同

场景推荐写法
只想拦截注解方法,不关心内容@annotation(com.xxx.PayLog)
需要读取注解参数(如 type、desc)@annotation(payLog) + PayLog payLog
想统一记录操作日志推荐带参数写法,灵活性更强

http://www.dtcms.com/a/486921.html

相关文章:

  • Linux设备模型
  • Linux fg命令使用教程
  • 微博爬虫流程解析——session的使用
  • 企业网站建设的核心是专业手机建站公司
  • Vllm Semantic-router MoM 架构
  • LLMs-from-scratch :KV 缓存
  • dshot协议数据帧格式
  • 华清远见25072班QT学习day1
  • 一个网站多个子域名优化网站系统建设与管理
  • SpringBoot使用LocalDate接收参数解析问题
  • 推荐系统学习笔记(十八)SECR-快手-用户留存建模
  • 自助网站建设技术支持建商城网站需要什么
  • 物联网设备安全接入管理系统的设计与核心功能
  • 在React中使用函数式编程的优点和缺点是什么?
  • UE5 Windows平台下打包Linux
  • UE5 建模专题 - 2:地形模式里的工具栏里的按钮的使用,以及样条点制作道路
  • 基于PHP+Mysql的旅游介绍网
  • HOW - prefetch 二级页面实践
  • OCR:开启档案管理的智能新时代
  • 设计网站官网入口广州做一个网站多少钱
  • 比较好的平面设计网站群晖nas安装wordpress安装
  • 重生之我在大学自学鸿蒙开发第六天-《组件导航》
  • Fragment如何实现Activity栈的压栈和出栈
  • 【组合数学题目】宇宙分解
  • 产品网站开发流程图多店铺开源商城系统
  • 百度收录好的网站免费h5网站制作平台
  • 包头微网站开发wordpress打赏作者插件
  • Rust数据库与工具的选择
  • 淮滨网站制作字体排版网站
  • Spring Boot 3.0 的架构革新:为何弃用 spring.factories 并转向 imports 文件