注解是在 JDK1.5 开始引入的特性,用户对包、类、接口、方法、字段、局部变量等进行解释说明
创建自定义注解时需要用到元注解,元注解可以用来描述自己创建的注解
目前元注解有四个:
@Target:
@Retention:
@Documented:
@Inherited:
详细解释元注解:
用于说明自定义注解所修饰的范围,有如下取值:
ElementType.PACKAGE: 包
ElementType.TYPE: 类、接口、Enum 声明
ElementType.METHOD: 方法
ElementType.FIELD: 字段
ElementType.LOCAL_VARIABLE: 局部变量
ElementType.PARAMETER: 参数
ElementType.CONSTRUCTOR: 构造器
eg:
@Target(ElementType.FIELD)
public @interface MyAnnotation {
String name() default "";
String no() default "";
}
说明注解的保留时间即该注解在什么范围内有效,有如下取值:
RetentionPolicy.SOURCE: 源文件
RetentionPolicy.CLASS: class 文件
RetentionPolicy.RUNTIME: 运行时
eg:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String name() default "";
String no() default "";
}
被该注解注释的自定义注解可以调用其他类型的注解
eg:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
String name() default "";
String no() default "";
}
若自定义注解被标注了 @Inherited,则被自定义注解标注的类的子类相当于同时也被标注了自定义注解
eg:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {
String name() default "";
String no() default "";
}
接下来需要用反射对注解进行解析操作
package com.annotation;
public class AnnotationTest {
@MyAnnotation(name = "this is name", no = "001")
private String name;
@MyAnnotation(name = "this is no", no = "002")
private String no;
}
package com.annotation;
import java.lang.reflect.Field;
public class AnnotationProcessor {
public static void main(String[] args) {
try {
Class clazz = AnnotationProcessor.class.getClassLoader().loadClass("com.annotation.AnnotationTest");
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
System.out.println("name: " + annotation.name() + ", no: " + annotation.no());
}
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
运行 AnnotationProcessor
实际中可以根据注解参数的不同内容进行不同的处理
若 @Target 的取值为 ElementType.METHOD 还可以利用 Spring 的 AOP 在方法调用前对其进行解析处理