1. 概念
1. 什么是注解
注解是 JDK 1.5 的时候引入的概念,是一种类似于注释的机制,他可以将任何的信息或元数据与程序元素(比如说 类 、变量 、成员方法等等)关联起来;为程序元素提供更加直观明了的说明,而这些说明信息不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用,并且供一些工具和框架使用。
注解更像是一种修饰符,他可以作用在包 、类 、构造器 、方法 、成员变量 、本地变量 、参数等等的说明语句上。
注解的本质是一个继承了 Annotation 的特殊接口,其具体实现类是 Java 运行时生成的动态代理类;所有的注解都存在于 java.lang.annotation 包中。
2. 元注解
元注解是用来自定义注解的,java.lang.annotation 包中有五个常用的元注解:
- @Documented:表示是否将注解信息添加在 java 文档中
- @Retention:用于描述注解的生命周期,表示需要在什么级别保存该注解,即保留的时间长短
- RetentionPolicy.SOURCE:在源文件中有效(即源文件保留)
- RetentionPolicy.CLASS:在class文件中有效(即class保留)
- RetentionPolicy.RUNTIME:在运行时有效(即运行时保留)
- @Target:用于描述注解的作用范围,即表示注解用于什么地方
- ElementType.CONSTRUCTOR:作用于构造器
- ElementType.FIELD:用于描述域即类成员变量
- ElementType.LOCAL_VARIABLE:用于描述局部变量
- ElementType.METHOD:用于描述方法
- ElementType.PACKAGE:用于描述包
- ElementType.PARAMETER:用于描述参数
- ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明
- ElementType.TYPE_PARAMETER:1.8版本开始,描述类、接口或enum参数的声明
- ElementType.TYPE_USE:1.8版本开始,描述一种类、接口或enum的使用声明
- @Inherited:表示被该注解标注的注解类型是可以被继承的,当然这种继承关系只在类继承的时候有效,像接口的继承,接口的实现是无效的。比如,如果一个类使用了 @Inherited 修饰的注解类型,则该类的子类将会继承这个注解类型
- @Repeatable:JDK 1.8 时引入的,用来标注一个注解是可重复注解
//声明 @Retention(RetentionPolicy.RUNTIME) @interface Schedules { Schedule[] value(); } @Repeatable(Schedules.class) @interface Schedule { String dayOfMonth() default "first"; String dayOfWeek() default "Mon"; int hour() default 12; }
//使用 @Schedule @Schedule @Schedule class TestRepeatable { @Schedule @Schedule int i; }
3. 注解处理器
注解处理器,如切面类就是一个注解处理器:注解处理器是使用注解整个流程中最重要的一步,所有在代码中出现的注解,它到底起了什么作用,都是在注解处理器中定义好的,注解本身并不会对程序的编译方式产生影响,而是注解处理器在起作用,注解处理器能够通过在运行时使用反射获取在程序代码中被使用的注解信息,从而实现一些额外功能,前提是我们自定义的注解使用的是 RetentionPolicy.RUNTIME 修饰的。
2. 利用反射获取注解信息
类注解:先拿到 Class 对象,再利用 getAnnotation() 等方法获取
方法注解:先拿到 Mehtod 对象,再利用 getAnnotation() 等方法获取
参数注解 (二维数组):先拿到 Mehtod 对象,再利用 getParameterAnnotations() 等方法获取
字段注解:先拿到 Field 对象,再利用 getDeclaredAnnotations() 等方法获取