news 2026/7/2 5:25:06

二(8.3):Java中的注解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二(8.3):Java中的注解

注解本身没有任何业务逻辑,它只是写在类、方法、属性或者参数上的“元数据”(用来描述数据的数据)。它就像是一张“便签纸”,贴在代码的各个角落,等着其他人(编译器或框架)来读取。

1. 注解的长相与结构

我们在代码里看到的 @Override、@Autowired、@Slf4j,它们的底层其实都是一种特殊的接口。

如果你自己去定义一个注解,代码长这样:

// 1. 🚨 关键:使用 @interface 来定义public@interfaceMyTag{// 注解的属性,长得很像方法Stringvalue()default"默认值";intage()default18;}

而在使用它的时候,就像在填表格:

@MyTag(value="正式员工",age=25)publicclassEmployee{// ...}

元注解(Meta-Annotations)

Java 官方为了让我们能控制自己写的注解,提供了几个专门用来修饰注解的注解,叫做元注解。

① @Target:限制这个标签能贴在哪里
你得规定这个便签是贴在“人(类)”额头上,还是贴在“手(方法)”上。

  • ElementType.TYPE:只能贴在类、接口、枚举上。
  • ElementType.METHOD:只能贴在方法上。
  • ElementType.FIELD:只能贴在属性字段上。

② @Retention:限制这个标签能活多久(生命周期)
这是注解最核心的属性,它决定了注解的命运,一共有三种寿命(三种策略):

  • RetentionPolicy.SOURCE(只活在源码期):
    代码编译成 .class 文件后,这个注解就消失了。
    代表作:@Override(给编译器看的)、Lombok 的 @Slf4j(编译完就卸磨杀驴)。

  • RetentionPolicy.CLASS(活到字节码期,默认):
    注解会被保留到 .class 文件里,但 JVM 启动加载它时,会把它丢弃。

  • RetentionPolicy.RUNTIME(活到运行期):
    系统运行起来后,注解依然常驻内存。
    代表作:Spring 的 @Controller、@Autowired。因为活得久,所以运行期可以通过反射去读取它。

3. 注解是如何生效的?

注解本身只是个死标签,如果不去读它,它和注释没有任何区别。能让它发挥魔法的,是背后的“注解处理器”。它主要分为两大门派:

门派 A:编译期动态修改(Lombok 派)

  • 寿命:SOURCE 级别。
  • 原理:Java 编译器在编译代码时,会调用它的插件(注解处理器)。插件发现有这个注解,就直接修改你的语法树,或者生成新的代码。
  • 结果:打出来的 .class 包里,注解没了,但多了很多行自动生成的代码。

门派 B:运行期反射解析(Spring / Hibernate 派)

  • 寿命:RUNTIME 级别。
  • 原理:程序启动后,Spring 等框架会化身“检查员”,利用 Java 反射机制 去遍历所有的类和方法,寻找特定的标签。
  • 结果:发现类上有 @Controller,就把它实例话放进容器;发现属性上有 @Autowired,就自动把对象塞进去。

4. 手写自定义注解

工作中 90% 的自定义注解都是为了结合反射,在运行时根据注解做逻辑处理(模仿 Spring 的 @Autowired 或 @RequestMapping)。

步骤 1:定义一个运行时注解

importjava.lang.annotation.*;// 1. 限定贴在 字段 上@Target(ElementType.FIELD)// 2. 必须保留到运行时(否则反射读不到)@Retention(RetentionPolicy.RUNTIME)public@interfaceMyAutowired{// 注解的属性:看起来像方法,使用时像变量Stringvalue()default"";// 默认值为空字符串}

步骤 2:使用该注解

publicclassUserService{@MyAutowired("注入用户服务实现")// 给属性贴标签privateStringserviceName;publicvoidprintService(){System.out.println("服务名:"+serviceName);}}

步骤 3:通过反射解析注解(核心逻辑)

importjava.lang.reflect.Field;publicclassAnnotationProcessor{publicstaticvoidmain(String[]args)throwsIllegalAccessException{UserServiceuserService=newUserService();// 获取所有字段(包括私有字段)Field[]fields=userService.getClass().getDeclaredFields();for(Fieldfield:fields){// 检查字段上是否贴了 @MyAutowired 注解if(field.isAnnotationPresent(MyAutowired.class)){// 读取注解上的值MyAutowiredannotation=field.getAnnotation(MyAutowired.class);StringinjectedValue=annotation.value();// 获取到 "注入用户服务实现"// 暴力破解私有权限,把值设进去(模拟依赖注入)field.setAccessible(true);field.set(userService,injectedValue);}}// 输出结果:服务名:注入用户服务实现userService.printService();}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 5:24:38

从零构建完整JMeter接口测试流程:核心原理与实战指南

1. 项目概述:从零构建一个完整的Jmeter接口测试流程如果你正在寻找一个能模拟真实用户行为、验证接口功能、甚至能进行压力测试的工具,那么Apache JMeter绝对是一个绕不开的名字。作为一个开源、免费且功能强大的性能测试工具,JMeter早已超越…

作者头像 李华
网站建设 2026/7/2 5:24:33

计算机Java毕设实战-基于 SpringBoot 的高校学生兼职求职管理系统的设计与实现 基于 SpringBoot 的校园助学岗位预约登记系【完整源码+LW+部署说明+演示视频,全bao一条龙等】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/7/2 5:20:13

Java毕业设计-基于 Java 的高中综合素质评价档案系统的设计与实现 基于 Java 的高中生社会实践档案管理系统(源码+LW+部署文档+全bao+远程调试+代码讲解等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华