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

SpringBoot 实现自定义注解

在 SpringBoot 中,自定义注解是非常实用的技术,常用于:日志记录、权限校验、接口限流、参数校验、事务增强、统一返回处理等。

核心原理:注解 + AOP(切面)实现(Spring AOP 基于动态代理)。

下面带你从零实现一个自定义日志注解(最通用、最易理解的案例)。


一、开发步骤

1. 引入依赖

需要spring-boot-starter-aop支持注解和切面:

<!-- Spring AOP 核心依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- web依赖(用于测试接口) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>

2. 自定义注解类

创建注解@LogRecord,用于标记需要记录日志的方法:

importjava.lang.annotation.*;/** * 自定义日志注解 * Target: 注解作用目标(METHOD=方法) * Retention: 注解生命周期(RUNTIME=运行时有效) */@Target(ElementType.METHOD)// 只作用在方法上@Retention(RetentionPolicy.RUNTIME)// 运行时生效@Documented// 生成文档public@interfaceLogRecord{// 注解属性:操作描述(默认空)StringoperateDesc()default"";}

3. 编写 AOP 切面(注解核心逻辑)

这是真正实现注解功能的地方,拦截加了@LogRecord的方法:

importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.JoinPoint;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.*;importorg.aspectj.lang.reflect.MethodSignature;importorg.springframework.stereotype.Component;importjava.lang.reflect.Method;@Aspect// 标记为切面类@Component// 交给 Spring 管理@Slf4jpublicclassLogRecordAspect{/** * 切点:匹配所有添加了 @LogRecord 注解的方法 */@Pointcut("@annotation(com.example.demo.annotation.LogRecord)")publicvoidlogPointCut(){}/** * 环绕通知:方法执行前后都拦截 */@Around("logPointCut()")publicObjectaround(ProceedingJoinPointpoint)throwsThrowable{longbeginTime=System.currentTimeMillis();// 执行目标方法Objectresult=point.proceed();// 执行耗时longtime=System.currentTimeMillis()-beginTime;// 保存日志recordLog(point,time);returnresult;}/** * 记录日志逻辑 */privatevoidrecordLog(ProceedingJoinPointjoinPoint,longtime){MethodSignaturesignature=(MethodSignature)joinPoint.getSignature();Methodmethod=signature.getMethod();// 获取自定义注解LogRecordlogAnnotation=method.getAnnotation(LogRecord.class);log.info("=====================日志开始====================");// 获取注解上的描述log.info("操作描述:{}",logAnnotation.operateDesc());// 获取方法名log.info("执行方法:{}",signature.getDeclaringTypeName()+"."+signature.getName());// 执行耗时log.info("执行耗时:{}ms",time);log.info("=====================日志结束====================");}}

4. 使用自定义注解

直接在Controller/Service 方法上添加@LogRecord

importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/test")publicclassTestController{/** * 使用自定义日志注解 */@LogRecord(operateDesc="测试自定义注解接口")@GetMapping("/annotation")publicStringtestAnnotation(){return"自定义注解生效啦!";}}

二、测试效果

启动项目,访问接口:
http://localhost:8080/test/annotation

控制台输出:

=====================日志开始==================== 操作描述:测试自定义注解接口 执行方法:com.example.demo.controller.TestController.testAnnotation 执行耗时:3ms =====================日志结束====================

自定义注解实现完成!


三、进阶:自定义注解常用场景扩展

1. 权限校验注解

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public@interfaceRequirePermission{Stringvalue();// 权限码}

切面中:获取当前登录用户权限 → 对比注解权限 → 无权限抛出异常。

2. 接口限流注解

切面中:使用 Redis + Lua 实现限流逻辑。

3. 参数非空校验注解

作用在参数/字段上,切面自动校验参数是否为空。


四、核心知识点总结

  1. 注解三要素

    • @Target:定义注解用在哪里(方法/类/参数)
    • @Retention:定义注解生命周期(必须用RUNTIME
    • @interface:声明自定义注解
  2. AOP 五大通知

    • @Around:环绕通知(最常用,前后都拦截)
    • @Before:方法执行前
    • @After:方法执行后
    • @AfterReturning:方法返回后
    • @AfterThrowing:方法异常后
  3. 核心原理
    Spring AOP 通过动态代理,拦截带有自定义注解的方法,执行增强逻辑。


总结

  1. 实现自定义注解 =定义注解 + AOP切面 + 使用注解
  2. 必须引入spring-boot-starter-aop依赖
  3. 注解本身无逻辑,逻辑全在 AOP 切面中
  4. 可用于日志、权限、限流、校验等场景
http://www.jsqmd.com/news/958575/

相关文章:

  • 别再只跑compile了!深入解读Design Compiler的compile_ultra与优化策略(以时序违例修复为例)
  • 拆解15元摇步神器:揭秘极简电磁摆的物理原理与成本控制
  • 基于claude code skills在快马平台开发电商商品管理系统的实战指南
  • 2026年铭博通风机靠谱吗? - mypinpai
  • 2026 EB-5移民中介哪家好?行业服务机构深度解析 - 品牌排行榜
  • 香薰工厂定制技术全解析:香薰推荐、香薰礼、香薰蜡烛、一站式香薰工厂、中国香薰工厂、义乌蜡烛、义乌香薰工厂、儿童香氛选择指南 - 优质品牌商家
  • 双向硅电压开关二极管,交流防护赛道核心器件!
  • Python 列表(List)与元组(Tuple)详解
  • RT-Thread串口DMA接收不定长数据,我用消息队列这么搞(附完整代码)
  • LIS2DW12在智能手环中的低功耗配置实战:如何将功耗降到1µA以下?
  • EB Garamond 12:如何为你的设计项目注入古典优雅气质
  • 小米手表表盘设计终极指南:零代码打造个性化智能穿戴界面
  • 2026江苏高职单招长期班优质机构推荐榜
  • SM内最多容纳多少线程?
  • WSL 2 + Docker 本地全栈开发环境配置指南
  • 驾驭未来:一文读懂智能驾驶中的深度学习模型
  • 2026新手开店靠谱加盟公司TOP5:开店攻略/开店选址/开店项目/新手开店/精品开店/莱啦开店加盟/集合店开店/选择指南 - 优质品牌商家
  • BiliSum开源:B站YouTube视频一键转笔记+思维导图,数据纯本地
  • Chinese-Medical-DIALOGUE-Data:构建中文医疗AI对话系统的终极实践指南
  • 微信小程序计算机毕设之微信小程序的博物馆文创商城系统的设计与实现基于springboot+微信小程序的博物馆文创系统的设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • 从充电头到高速传输:手把手教你根据项目需求选对Type-C引脚方案(附PCB布局建议)
  • 音乐解锁神器:5分钟打破平台加密,让付费音乐真正属于你!
  • Java+MySQL+Mybatis+Junit4实现学生信息管理系统
  • 为何VMware上云之路充满挑战?
  • 递归函数的设计方法
  • 1分钟教你如何AI生图
  • 2026年养殖池防渗膜市场新观察:陵县源头厂家的核心价值与选择逻辑 - 2026年企业资讯
  • M4Markets整体表现账户稳吗?
  • 费县实操为主的家电清洗培训学校 行业入门标准与培训流程科普
  • Spring Boot:整合Quartz集群部署指南