序言
事不凝滞,理贵变通。
写框架离不开Java注解,今天来总结一下。
Java元注解
四个:@Retention @Target @Docuement @Inherited
元注解,用来标注注解的注解。
@Retention:注解的保留位置
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在编译期就被丢掉了,不会被class包含。
@Retention(RetentionPolicy.CLASS) // 不会加载进JVM,注解会在class字节码文件中存在,但运行时无法获得。
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到。
这里如果@Retention未标注,默认是CLASS阶段。
通常我们自定义的都是RUNTIME阶段,一定要标注。
@Target:注解的作用目标
@Target(ElementType.TYPE) //接口、类、枚举
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解。
@Inherited仅针对@Target(ElementType.TYPE)类型的注解有效,并且仅针对类的继承,对接口的继承无效。
Java注解的使用
注解可以附加在程序元素( 包、类、构造器、方法、成员变量、参数、局域变量 )上面,为其添加额外的辅助信息,可以通过反射机制访问这些数据。
写个小demo:
1 | (RetentionPolicy.RUNTIME) |
本注解仅针对method,作用在runtime阶段。
使用该注解的方式应为:
1 | (id=xxx,type=xxx,level=xxx,value=xxx) |
default的意义在于如果使用注解的时候未给参数赋值,可以采用default预先写好的值。
如果注解想在多个target使用:
1 | (RetentionPolicy.RUNTIME) |
自定义注解
必须要写:
- @Target
- @Retention
可定义多个参数和默认值,核心参数使用value名称。
应当设置@Retention(RetentionPolicy.RUNTIME)便于运行期读取该Annotation。
Java提供的使用反射API读取Annotation
的方法包括:
判断某个注解是否存在于Class
、Field
、Method
或Constructor
:
Class.isAnnotationPresent(Class)
Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
例如:
1 | // 判断@Report是否存在于Person类: |
使用反射API读取Annotation:
Class.getAnnotation(Class)
Field.getAnnotation(Class)
Method.getAnnotation(Class)
Constructor.getAnnotation(Class)
例如:
1 | // 获取Person定义的@Report注解: |
demo:
1 | (RetentionPolicy.RUNTIME) |
某个JavaBean:
1 | public class Person { |
编写一个Person
实例的检查方法,它可以检查Person
实例的String
字段长度是否满足@Range
的定义:
1 | void check(Person person) throws Exception{ |
参考: