注解的本质就是一个继承了Annotation接口的接口,一个注解准确意义上来说,只不过是一种特殊注释而已,如果没有解析他的代码,他可能连注释都不如。 解析一个类或者方法的注解往往有两种形式,一种是编译期直接的扫描,一种是运行期反射。
Java中有以下几个元注解
@Target: 注解的作用目标@Retention: 注解的生命周期@Documented: 注解是否应当被包含在javaDoc文档中@Inherited: 是否允许子类继承该注解
1)@Target中作用范围对应的枚举值:
ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上ElementType.FIELD:允许作用在属性字段上ElementType.METHOD:允许作用在方法上ElementType.PARAMETER:允许作用在方法参数上ElementType.CONSTRUCTOR:允许作用在构造器上ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上ElementType.ANNOTATION_TYPE:允许作用在注解上ElementType.PACKAGE:允许作用在包上
2)@RetentionPolicyd取值对应枚举:RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件RetentionPolicy.RUNTIME:永久保存,可以反射获取3)@Inherited 注解修饰的注解是具有可继承性的,也就说我们的注解修饰了一个类,而该类的子类将自动继承父类的该注解注解和反射虚拟机规范定义了一系列和注解相关的属性表,也就是说,无论是字段、方法或者是类本身,如果被注解修饰了,就可以被写进字节码文件,属性表有以下几种:RuntimeVisibleAnnotations:运行时可见的注解RuntimeInVisibleAnnotations:运行时不可见的注解RuntimeVisibleParameterAnnotations:运行时可见的方法参数注解RuntimeInVisibleParameterAnnotations:运行时不可见的方法参数注解AnnotationDefault:注解类元素的默认值所以,对于一个类或者接口来说,Class类中提供以下一些方法用于反射注解getAnnotation:返回指定的注解isAnnotationPresent:判定当前元素是否被指定注解修饰getAnnotations:返回所有的注解getDeclaredAnnotation:返回本元素的指定注解getDeclaredAnnotations:返回本元素的所有注解,不包含父类继承而来的
总结首先,我们通过键值对的形式可以为注解属性赋值。接着,你用注解修饰某个元素,编译器将在编译期扫描每个类或者方法上的注解,会做一个基本的检查,你的这个注解是否允许作用在当前位置,最后会将注解信息写入元素的属性表。然后,当你进行反射的时候,虚拟机将所有生命周期在 RUNTIME 的注解取出来放到一个 map 中,并创建一个 AnnotationInvocationHandler 实例,把这个 map 传递给它。最后,虚拟机将采用 JDK 动态代理机制生成一个目标注解的代理类,并初始化好处理器。那么这样,一个注解的实例就创建出来了,它本质上就是一个代理类,你应当去理解好 AnnotationInvocationHandler 中 invoke 方法的实现逻辑,这是核心。一句话概括就是,通过方法名返回注解属性值
转载于:https://www.cnblogs.com/gimgoog/p/10196651.html