注解(Annotation)原理与自定义注解实战:你不懂的注解背后究竟发生了什么?

举报
喵手 发表于 2025/12/08 20:23:01 2025/12/08
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在 Java 编程中,注解(Annotation)这一概念虽然很常见,但很多开发者在使用时,可能只是停留在“用来做标记、配置”这一层面。你是不是也觉得,注解就是加在类、方法、字段前面的一些小符号,能够影响程序的行为,但并没深究过它背后的原理和使用技巧?

其实,注解在 Java 中扮演着非常重要的角色,它不仅仅是“装饰器”,更是编译期、类加载期甚至运行时的一种强大工具。今天,我们不仅要了解注解的基本原理,还将通过自定义注解的实战,带你进入注解的“魔法世界”,让你不再仅仅满足于“好用”,而是深入理解注解背后的设计思想和应用场景。

所以,坐稳了,接下来我们一起深入探索注解的奥秘,搞定自定义注解这门“黑魔法”!

一、注解是什么?

注解,从字面上来看,它就是对代码的元数据注解。也就是说,它不会直接影响程序的逻辑行为,但能通过某些工具或框架读取并执行对应的功能。Java 中的注解并不是程序执行的一部分,而是用来描述程序的结构、元信息,甚至在特定的情况下改变程序的行为。

注解的基本用法

注解的定义非常简单,语法结构类似于接口。常见的注解如 @Override@Deprecated@Entity 等。它们一般不会影响程序的执行,而是给编译器或者运行时提供一些额外的信息。

// 使用 @Override 注解表示该方法重写了父类的方法
@Override
public String toString() {
    return "Hello, World!";
}

// 使用 @Deprecated 注解表示该方法已过时,不推荐使用
@Deprecated
public void oldMethod() {
    System.out.println("This method is outdated!");
}

1. 基本语法

@interface MyAnnotation {
    // 定义一个注解
    String value() default "Default";
}

简单来说,注解就是用 @ 开头的特殊标记,它可以附加在类、方法、字段、参数等位置。

二、注解的原理:编译期、类加载期、运行时的作用

1. 编译期(注解不参与程序运行)

注解可以在编译时用于检查,比如 @Override,它会帮助编译器检查我们是否真正重写了父类方法。如果我们用 @Override 注解修饰的方法在父类中不存在,编译器会报错。

@Override
public void someMethod() {  // 编译期检查父类是否有该方法
    System.out.println("Hello");
}

2. 类加载期(注解可以用作元数据)

注解还可以在类加载期间用于一些框架或工具类的处理,比如 Spring 框架就是通过注解(如 @Autowired)来实现依赖注入的。

3. 运行时(注解的核心应用)

注解的最强大之处是在运行时,它能通过反射机制被程序读取并执行。比如使用 @Entity 注解标记的类,ORM 框架(如 Hibernate)会在程序启动时通过反射读取注解信息,进而将该类映射成数据库表。

@Entity
public class User {
    @Id
    private Long id;
    
    private String name;
}

三、注解的分类

Java 中的注解有多种分类方式,按照作用域和生命周期,常见的分类方式如下:

  1. 标准注解(Built-in Annotations)

    • @Override:标识重写父类的方法。
    • @Deprecated:标记该方法或类已经不推荐使用。
    • @SuppressWarnings:抑制编译器警告。
  2. 元注解(Meta-Annotations)

    • @Retention:定义注解的生命周期。
    • @Target:指定注解可以应用于哪些元素(类、方法、字段等)。
    • @Inherited:使得注解可以从父类继承到子类。
    • @Documented:使注解能够包含在 Javadoc 中。
  3. 自定义注解(Custom Annotations)

我们可以根据需要自定义注解,下面将通过一个实际的案例来演示如何定义和使用自定义注解。

四、自定义注解实战:我们来造一个“黑魔法”注解

1. 定义一个自定义注解

我们先定义一个注解,用于标记方法是否需要进行日志记录。

// 定义注解
@Retention(RetentionPolicy.RUNTIME)  // 注解在运行时有效
@Target(ElementType.METHOD)          // 注解只能应用于方法上
public @interface LogExecutionTime {
    // 你可以在注解中定义元素,作为附加信息
}

这里的 @Retention(RetentionPolicy.RUNTIME) 表示注解会在运行时通过反射获取,@Target(ElementType.METHOD) 表示注解只能用在方法上。

2. 使用自定义注解

接下来我们用这个注解来标记需要记录执行时间的方法:

public class MyService {

    @LogExecutionTime  // 标记需要记录执行时间
    public void processData() {
        // 模拟一些耗时操作
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3. 创建注解处理器(处理注解逻辑)

接下来,我们创建一个注解处理器,通过反射扫描 @LogExecutionTime 注解,并记录方法的执行时间:

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class LogExecutionTimeProcessor {
    public static void process(Object object) throws Exception {
        // 获取对象的所有方法
        Method[] methods = object.getClass().getMethods();

        for (Method method : methods) {
            // 检查方法上是否有 @LogExecutionTime 注解
            if (method.isAnnotationPresent(LogExecutionTime.class)) {
                long startTime = System.currentTimeMillis();

                // 执行方法
                method.invoke(object);

                long endTime = System.currentTimeMillis();
                System.out.println("Execution time of " + method.getName() + ": " + (endTime - startTime) + " ms");
            }
        }
    }
}

4. 测试

main 方法中,我们创建 MyService 对象并使用注解处理器来记录方法执行时间:

public class Main {
    public static void main(String[] args) throws Exception {
        MyService myService = new MyService();
        LogExecutionTimeProcessor.process(myService);
    }
}

5. 结果

程序运行后,输出类似以下内容:

Execution time of processData: 1001 ms

这就实现了通过自定义注解来记录方法的执行时间。注解的真正威力在于,它能够让我们的代码更加简洁,并且通过注解处理器灵活地控制行为。

五、注解的高级应用:Spring 和 Hibernate

在框架中,注解的使用已经达到极致,尤其是 Spring 和 Hibernate 这样的框架,它们几乎所有的功能都依赖于注解进行配置。比如:

  • Spring 注解@Autowired@Component@Service@RequestMapping 等,Spring 容器通过这些注解来进行自动化装配和控制反转(IoC)。

  • Hibernate 注解@Entity@Id@Column 等,Hibernate 使用这些注解来映射 Java 类与数据库表之间的关系。

这些框架的工作原理,实际上都是通过扫描这些注解并通过反射获取相关信息,最终动态生成代码执行操作。

六、总结

通过今天的讲解,我们已经从注解的基础用法到自定义注解的实战应用,都有了全面的了解。你会发现,注解不仅仅是一个简单的标记,它的设计原理和应用场景都充满了“魔力”,它能够大大简化开发中的许多复杂任务。

核心总结:

  1. 注解的作用:通过元数据来描述程序的结构或提供额外的信息,不直接影响程序的逻辑。
  2. 自定义注解的优势:通过反射机制,能够在运行时灵活地处理业务逻辑,提高程序的可扩展性和解耦性。
  3. 高级应用:注解在 Spring、Hibernate 等框架中得到广泛应用,真正体现了注解在代码中的“黑魔法”力量。注解(Annotation)原理与自定义注解实战:你不懂的注解背后究竟发生了什么?

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。