转载

java反射原理, 注解原理

阅读更多

注解机制及原理

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高可用

  • 13 分钟前
  • 浏览 0
  • 分类:编程语言
  • 查看更多

评论

发表评论

java反射原理, 注解原理 您还没有登录,请您登录后再发表评论

原文  https://uule.iteye.com/blog/2436297
正文到此结束
Loading...