元注解
Java中的元注解(Meta-Annotation),简单来说就是**“用来修饰注解的注解”**。
在Java中,我们可以自己定义注解,但光定义一个空壳注解是没用的。我们需要通过元注解来告诉编译器或JVM:这个自定义的注解能写在哪里?它的生命周期有多长?会不会被继承?
JDK原生提供了几个核心的元注解,其中最常用、最核心的有以下4个:
1. @Target(指定作用范围)
它用来限制你的注解可以写在哪些位置。比如,你希望某个注解只能写在方法上,或者只能写在类上,就需要用到它。它的取值是 ElementType 枚举,常见的有:
ElementType.TYPE:可以作用在类、接口、枚举上。ElementType.FIELD:可以作用在成员变量(字段)上。ElementType.METHOD:可以作用在成员方法上。ElementType.PARAMETER:可以作用在方法参数上。
2. @Retention(指定生命周期)
它用来决定你的注解能保留到什么时候,这是元注解里最核心的一个。它的取值是 RetentionPolicy 枚举,分为三个阶段:
RetentionPolicy.SOURCE:注解只保留在源码中,编译成.class文件时就会被丢弃(比如我们常用的@Override)。RetentionPolicy.CLASS:注解保留在.class字节码文件中,但在JVM运行时不会被加载到内存(这是默认值)。RetentionPolicy.RUNTIME:注解不仅保留在.class中,还会被JVM加载到内存。只有设置为 RUNTIME,你的程序才能在运行时通过反射(Reflection)获取到注解信息。我们平时用的 Spring 框架中的@Autowired、@Controller等,底层都是 RUNTIME。
3. @Documented(生成文档)
这是一个标记注解。默认情况下,使用 javadoc 工具生成API文档时,是不会把注解信息包含进去的。如果你的自定义注解上加了 @Documented,那么在生成文档时,这个注解也会作为说明的一部分出现在生成的 HTML 文档里。
4. @Inherited(允许继承)
它用来规定注解是否具有继承性。如果一个父类上加了被 @Inherited 修饰的注解,那么它的子类在没有加任何注解的情况下,会自动继承父类的这个注解。
注意:这个元注解只对类级别的注解(即 @Target 为 TYPE)有效,对方法和字段无效。
结合黑马课程实战举例
为了更好理解,我们正在学的 Spring 来举个例子。在 Spring Boot 中,我们经常用到 @RestController 或 @Service,这些其实就是 Spring 框架帮咱们定义好的自定义注解。
如果我们自己来模拟定义一个类似 @Service 的注解,代码大概长这样:
|
|
因为 @Retention 设置成了 RUNTIME,Spring 容器在启动的时候,才能通过反射机制去扫描你项目里的所有类,看看哪些类头上顶着 @MyService(或 @Service),然后把这些类自动创建成对象(Bean)并管理起来。
简单总结一下:元注解就是给自定义注解立规矩的“幕后大佬”,尤其是 @Target 和 @Retention,在后续学习 Spring 等框架的底层原理时会非常关键!