阅读更多
注解机制及原理
JAVA注解原理详解
深入理解注解实现原理
java.lang.annotation提供了四种 元注解 ,专门注解其他的注解:
@Documented
@Retention
@Target
@Inherited
@Documented –注解是否将包含在JavaDoc中
@Retention –什么时候使用该注解
RetentionPolicy.SOURCE
– 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。
@Override, @SuppressWarnings都属于这类注解。
@Override告诉编译器这个方法是一个重写方法(描述方法的元数据),如果父类中不存在该方法,编译器便会报错,提示该方法没有重写父类中的方法。如果我不小心拼写错误,例如将toString()写成了toStrring(){double r},而且我也没有使用@Override注解,那程序依然能编译运行。但运行结果会和我期望的大不相同。
RetentionPolicy.CLASS
– 在类加载的时候丢弃。在字节码文件的处理中有用。【注解默认使用这种方式。】
RetentionPolicy.RUNTIME
– 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
@Target –注解用于什么地方
@Inherited – 是否允许子类继承该注解
这4个元注解都是在jdk的java.lang.annotation包下面
Test t = AnnotationTest.class.getAnnotation(Test.class); tm = AnnotationTest.class.getDeclaredMethod("test",null).getAnnotation(TestMethod.class); AnnotationTest.class.getDeclaredField("field").getAnnotation(MyAnTargetField.class);
从上面的句子就可以看出,它是 【从class结构中获取出Test注解的】 ,所以肯定是在某个时候注解被加入到class结构中去了。
从java源码到class字节码是由编译器完成的,而注解也是在编译时由编译器进行处理, 【编译器会对注解符号处理并附加到class结构中】 ,根据jvm规范,class文件结构是严格有序的格式, 唯一可以附加信息到class结构中的方式就是【保存到class结构的attributes属性中】 。我们知道对于类、字段、方法,在class结构中都有自己特定的表结构,而且各自都有自己的属性,而对于注解,作用的范围也可以不同,可以作用在类上,也可以作用在字段或方法上,这时编译器会对应将注解信息存放到类、字段、方法自己的属性上。
在我们的AnnotationTest类被编译后,在对应的AnnotationTest.class文件中会包含一个RuntimeVisibleAnnotations属性,由于这个注解是作用在类上,所以此属性被添加到类的属性集上。即Test注解的键值对value=test会被记录起来。而当JVM加载AnnotationTest.class文件字节码时,就会将RuntimeVisibleAnnotations属性值保存到AnnotationTest的Class对象中,于是就可以通过AnnotationTest.class.getAnnotation(Test.class)获取到Test注解对象,进而再通过Test注解对象获取到Test里面的属性值。
其实注解被编译后的本质就是一个 继承Annotation接口的接口 ,所以@Test其实就是
public interface Test extends Annotation
当我们通过AnnotationTest.class.getAnnotation(Test.class)调用时, JDK会通过动态代理生成一个实现了Test接口的对象 ,并将RuntimeVisibleAnnotations属性值设置进此对象中,此对象即为Test注解对象,通过它的value()方法就可以获取到注解值。
分享到:
Nginx负载均衡+Keepalived高可用
您还没有登录,请您登录后再发表评论