JAVA 注解(Annotation):从原理到实战应用

news2026/3/30 21:04:55
在 Java 5 及后续版本中注解Annotation作为一种元数据编程机制彻底改变了 Java 的配置与框架开发模式。它不再是简单的代码注释而是能被编译器、虚拟机、框架解析的结构化标记广泛应用于 Spring Boot、MyBatis、Lombok 等主流技术栈是 Java 后端开发者从基础进阶到高级的核心知识点。本文将从底层原理、元注解、内置注解、自定义注解、实战落地、性能优化六大维度深度拆解 Java 注解搭配可直接运行的企业级代码帮助开发者彻底掌握注解的本质与用法。一、注解的核心定义与底层原理1.1 什么是注解注解是 Java 提供的代码级元数据用于为类、方法、字段、参数等程序元素附加额外信息这些信息不直接改变业务逻辑但可在编译期、类加载期、运行期被解析实现代码增强、配置绑定、语法检查等功能。简单来说注解就是给代码打标签让程序能读懂这些标签并执行对应逻辑。1.2 注解的本质特殊的接口很多开发者误以为注解是 “高级注释”这是完全错误的认知。从 JVM 底层来看注解本质是继承了java.lang.annotation.Annotation接口的特殊接口。当我们用interface定义注解时编译器会自动将其转换为继承Annotation的接口JVM 在运行时通过动态代理生成注解的实现类这也是注解能存储属性、被反射读取的核心原因。通过反编译注解字节码可验证这一结论运行// 自定义注解 public interface MyAnnotation { String value(); } // 反编译后生成的接口 public interface MyAnnotation extends java.lang.annotation.Annotation { String value(); }1.3 注解的生命周期与解析机制注解的生命周期由Retention元注解控制分为三个阶段对应不同的解析方式源码阶段SOURCE仅存在于 Java 源码中编译为 class 文件时被丢弃用于编译器检查如Override字节码阶段CLASS存在于 class 文件中类加载时被 JVM 丢弃用于字节码增强、代码生成如 Lombok运行时阶段RUNTIME全程保留可通过Java 反射机制在运行时读取是框架开发的核心如Autowired、RequestMapping。其中运行时注解是企业开发最常用的类型依赖Class、Method、Field等反射类的getAnnotation()、isAnnotationPresent()方法实现解析。二、元注解注解的 “规则制定者”元注解是 JDK 提供的用于修饰自定义注解的注解共 4 个核心元注解负责约束自定义注解的作用范围、生命周期、继承性等规则是自定义注解的基础。2.1 Target指定注解作用目标用于限定注解能修饰的程序元素参数为ElementType枚举常用值TYPE类、接口、枚举METHOD成员方法FIELD成员变量含枚举常量PARAMETER方法参数CONSTRUCTOR构造方法ANNOTATION_TYPE注解本身。2.2 Retention指定注解生命周期这是自定义注解必须配置的元注解决定注解的存活时间参数为RetentionPolicy枚举SOURCE源码级编译丢弃CLASS字节码级类加载丢弃默认值RUNTIME运行时级可反射解析。2.3 Documented生成 API 文档标记该注解会被javadoc工具提取到 API 文档中让注解信息在文档中可见。2.4 Inherited注解继承性标记该注解可被子类继承仅对类级别注解有效方法、字段注解不支持继承。三、JDK 内置注解基础用法与场景JDK 提供了 3 个核心内置注解用于基础语法检查是日常开发中最常用的注解3.1 Override方法重写校验标记方法重写父类或接口的方法编译器会强制校验方法签名返回值、方法名、参数是否匹配避免重写错误。java运行public class Parent { public void sayHello() {} } public class Child extends Parent { Override public void sayHello() { // 编译通过 www.cqqjsyzx.com/caishenSystem.out.println(重写父类方法); } // Override public void sayHi() { // 取消注解编译通过添加注解编译报错 System.out.println(非重写方法); } }3.2 Deprecated标记过时元素标记类、方法、字段已过时不推荐使用编译器会发出警告常用于版本迭代中的废弃 API。3.3 SuppressWarnings抑制编译器警告用于抑制编译器的特定警告如未检查转换、过时调用参数为警告类型常用unchecked、deprecation、all。四、自定义注解从定义到解析全流程自定义注解是企业开发的核心能力用于实现日志记录、权限校验、参数验证、ORM 映射等通用功能简化重复代码。自定义注解的标准流程定义注解→使用注解→解析注解。4.1 自定义注解语法java运行// 元注解约束 Target({ElementType.METHOD, ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented public interface 注解名 { // 注解属性类型 属性名() [default 默认值]; String value(); // 核心属性使用时可省略属性名 int age() default 18; // 带默认值的属性 boolean required() default true; }注解属性支持的类型基本数据类型、String、Class、枚举、注解、以上类型的数组。4.2 实战 1自定义日志注解 反射解析实现一个方法日志注解自动记录方法执行时间、入参、出参通过反射解析注解并执行日志逻辑。步骤 1定义日志注解java运行import java.lang.annotation.*; /** * 自定义方法日志注解 */ Target(ElementType.METHOD) // 仅作用于方法 Retention(www.cqqjsyzx.comRetentionPolicy.RUNTIME) // 运行时生效 Documented public interface MethodLog { // 方法描述 String desc() default ; // 是否记录执行时间 boolean recordTime() default true; // 是否记录入参 boolean recordParams() default true; }步骤 2使用注解标记业务方法java运行public class UserService { MethodLog(desc 根据用户ID查询用户信息, recordTime true) public String getUserById(Long userId) { return 用户ID userId 用户名Java开发者; } MethodLog(desc 添加用户, recordParams true) public boolean addUser(String username, Integer age) { System.out.println(执行添加用户逻辑 username); return true; } }步骤 3反射解析注解核心java运行import java.lang.reflect.Method; public class LogAnnotationParser { public static void parseAndExecute(Object obj) throws Exception { Class? clazz obj.getClass(); Method[] methods clazz.getDeclaredMethods(); // 遍历所有方法解析MethodLog注解 for (Method method : methods) { if (method.isAnnotationwww.cqqjsyzx.com/jiri/Present(MethodLog.class)) { MethodLog log method.getAnnotation(MethodLog.class); long startTime System.currentTimeMillis(); // 执行方法 Object result method.invoke(obj, 1001L, 张三, 25); // 记录日志 System.out.println(方法日志); System.out.println(方法描述 log.desc()); System.out.println(方法名 method.getName()); if (log.recordParams()) { System.out.println(入参 1001, 张三, 25); } if (log.recordTime()) { long costTime System.currentTimeMillis() - startTime; System.out.println(执行耗时 costTime ms); } System.out.println(执行结果 result); System.out.println(\n); } } } // 测试 public static void main(String[] args) throws Exception { UserService userService new UserService(); parseAndExecute(userService); } }4.3 实战 2自定义权限注解 AOP 增强在 Spring Boot 项目中结合 AOP 实现接口权限校验通过注解标记需要权限控制的方法无需侵入业务代码。步骤 1定义权限注解java运行import java.lang.annotation.*; Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) Documented public interface RequirePermission { // 所需权限编码 String[] value(); }步骤 2AOP 切面解析注解java运行import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; Aspect Component public class PermissionAspect { // 模拟当前用户权限 private static final ListStringwww.cqqjsyzx.com USER_PERMISSIONS Arrays.asList(user:query, user:add); Around(annotation(com.example.annotation.RequirePermission)) public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature (MethodSignature) joinPoint.getSignature(); Method method signature.getMethod(); // 获取注解信息 RequirePermission permission method.getAnnotation(RequirePermission.class); String[] requiredPermissions permission.value(); // 权限校验 for (String p : requiredPermissions) { if (!USER_PERMISSIONS.contains(p)) { throw new RuntimeException(权限不足需要权限 Arrays.toString(requiredPermissions)); } } // 执行目标方法 return joinPoint.proceed(); } }步骤 3使用注解java运行import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; RestController public class UserController { GetMapping(/user/query)www.cqqjsyzx.com/bazi RequirePermission(user:query) public String queryUser() { return 查询用户成功; } GetMapping(/user/delete) RequirePermission(user:delete) public String deleteUser() { return 删除用户成功; } }访问/user/delete时会抛出 “权限不足” 异常实现无侵入式权限控制。五、注解在主流框架中的应用注解是 Java 框架的核心灵魂几乎所有主流框架都基于注解实现简化开发以下是三大框架的注解应用解析5.1 Spring/Spring Boot注解驱动开发Spring Boot 彻底抛弃 XML 配置通过注解实现 IoC、AOP、事务、Web 请求绑定SpringBootApplication启动类核心注解整合Configuration、ComponentScan、EnableAutoConfigurationControllerwww.cqqjsyzx.com/qiming/RestController标记 Web 控制器Autowired依赖注入自动装配 BeanTransactional声明式事务管理。5.2 MyBatisORM 映射注解替代 Mapper XML 文件通过注解直接在接口方法上编写 SQL简化持久层开发Select查询注解Insert插入注解Update更新注解Delete删除注解。java运行public interface UserMapper { Select(SELECT * FROM user WHERE id #{id}) User selectById(Long id); }5.3 Lombok编译期注解简化代码Lombok 通过编译期注解处理器APT在编译时自动生成 getter/setter、构造方法、toString 等代码减少样板代码Data自动生成 getter/setter、equals、hashCode、toStringNoArgsConstructorwww.cqqjsyzx.com/wuxing/AllArgsConstructor无参 / 全参构造器Slf4j自动注入日志对象。java运行import lombok.Data; Data public class User { private Long id; private String username; private Integer age; }六、注解开发的常见坑与优化方案6.1 注解生命周期配置错误问题使用CLASS级别注解运行时反射获取不到解决方案运行时解析必须配置Retention(RetentionPolicy.RUNTIME)。6.2 反射解析性能损耗问题频繁反射解析注解导致接口性能下降解决方案启动时一次性解析注解并缓存避免运行时重复反射。6.3 过度使用注解问题将所有配置都用注解实现导致代码耦合度高、难以维护解决方案动态配置如数据库配置、环境变量用外部配置文件静态规则用注解。6.4 注解属性类型错误问题注解属性使用不支持的类型如 Object、集合编译报错解决方案仅使用基本类型、String、Class、枚举、注解及对应数组。七、总结Java 注解不是简单的 “代码标签”而是元数据编程的核心工具是连接业务代码与框架逻辑的桥梁。从底层原理来看注解是特殊接口 动态代理的结合体从应用层面来看注解实现了配置与代码的一体化大幅简化开发流程。掌握注解的核心要点本质继承Annotation的特殊接口运行时由动态代理实现核心约束元注解Target作用目标、Retention生命周期是自定义注解的基础解析方式运行时注解靠反射编译时注解靠APT实战核心自定义注解 反射 / AOP实现日志、权限、参数校验等通用功能框架应用Spring、MyBatis、Lombok 的核心能力都基于注解。无论是面试还是企业开发深入理解注解原理、熟练编写自定义注解都是 Java 开发者的必备技能。只有吃透注解的本质才能读懂框架源码、设计高可用的企业级组件实现从 “会用” 到 “精通” 的进阶。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2466199.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…