注解 Annotation(也叫元数据 metadata),是 Java 提供的一种标识代码的方式。注解相当于一种标记,在代码中加了注解之后,JAVAC 编译器,开发工具和其他程序就可以用反射来了解代码中类以及各种元素上有无标记,以及获取到具体的标记之后,处理对应的逻辑
定义
一个注解就是一个类,定义方式为:
@interface Annotation{}
举例(@Override)
比如我们常见的 @Override
注解,还有 @Deprecated
、@SuppressWarnings
等注解,
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
元注解
元注解就是用来修饰注解的注解,比如上面
@Override
注解上的@Target
、@Retention
@Target 元注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
它有一个属性:ElementType
,是一个枚举类型的数组,值为:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
表示被标注的注解可以标识在哪些类型上面(类、接口、方法、字段声明、参数、构造器、注解、包等类型),比如 @Target(ElementType.METHOD)
修饰的注解表示该注解只能用来修饰在方法上,如果修饰在类上,则编译报错
@Retention 元注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
它也是有一个属性:RetentionPolicy
枚举类型,可用的值有:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
这个属性表示注解的保留策略,表示被标注的注解的信息保留阶段:
- CLASS:表示被标注的注解的信息被保留在 class文件(字节码文件)中当程序编译时,但不会被虚拟机读取(运行时)
- SOURCE:表示被标注的注解的信息会被编译器抛弃,不会保留在 class 文件中,只会留在源文件中
- RUNTIME:表示被标注的注解的信息被保留在 class 文件(字节码文件)中,当程序编译时,会被保留在虚拟机中(运行时),所以可以通过反射的方式读取(一般我们自定义的注解都是这个类型)。
注解的应用(自定义注解)
在日常 web 开发中,我们可能会在代码的任一方法中获取用户信息,此时我们可以利用注解的方式,在方法中的某个参数上标注一个注解,在运行时,通过反射的方式获取到这个注解,然后给注解修饰的参数赋值,就实现了用户信息的注入。举例:
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}
这里我们只是定义了一个注解,具体如何通过这个注解来实现上述功能,我们在 SpringBoot - 自定义注解 @CurrentUser 注入当前登录用户信息
这篇文章中实现。