学习注解Annotation的原理,这篇讲的不错:http://blog.csdn.net/lylwo317/article/details/52163304

先自定义一个运行时注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface HelloAnnotation { String say() default "Hi"; }

然后在Main函数中解析注解

@HelloAnnotation(say = "Do it!")
public class TestMain {
public static void main(String[] args) {
HelloAnnotation annotation = TestMain.class.getAnnotation(HelloAnnotation.class);//获取TestMain类上的注解对象
System.out.println(annotation.say());//调用注解对象的say方法,并打印到控制台
}
}

HelloAnnotation注解的实例是jvm生成的动态代理类的对象。

这个运行时生成的动态代理对象是可以导出到文件的,方法有两种

  1. 在代码中加入System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
  2. 在运行时加入jvm 参数 -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true

可以看到,我们自定义的注解HelloAnnotation是一个接口,而$Proxy1这个Java生成的动态代理类就是它的实现类

很明显,HelloAnnotation就是继承了Annotation的接口。再看第10行,flag字段中,我们可以看到,有个ACC_ANNOTATION标记,说明是一个注解,所以注解本质是一个继承了Annotation的特殊接口。

而Annotation接口声明了以下方法。

package java.lang.annotation;

public interface Annotation {
boolean equals(Object var1); int hashCode(); String toString(); Class<? extends Annotation> annotationType();
}

这些方法,已经被$Proxy1实现了。(这就是动态代理的机制)

无论是否了解动态代理,这里只需要明确一点,动态代理方法的调用最终会传递给绑定的InvocationHandler实例的invoke方法处理。

从上面不难看出,say方法最终会执行(String)super.h.invoke(this, m3, (Object[])null);,而这其中的h对象类型就是InvocationHandler接口的某个实现类。

可以看到h对象是AnnotationInvocationHandler的实例。让我们来看看该实现类的invoke方法。

可以看到,say方法的返回值是从一个Map中获取到的。这个map以key(注解方法名)—value(注解方法对应的值)存储TestMain类上的注解

那memberValues这个Map对象是怎么生成的,继续调试 
通过方法调用栈找到memberValues的本源。

可以看到,memberValues是通过常量池获取到,return var2.getUTF8At(var3);中的var3就是常量池中的序号。继续执行返回到parseMemberValue()方法。可以看到获取的就是我们定义在TestMain类上注解的say的值——“Do it!”。

小结

现在我们知道了HelloAnnotation注解(接口)是一个继承了Annotation接口的特殊接口,而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1,该类就是HelloAnnotation注解(接口)的具体实现类。

注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。

Java注解Annotation学习的更多相关文章

  1. Java注解Annotation学习笔记

    一.自定义注解 1. 使用关键字 @interface 2. 默认情况下,注解可以修饰 类.方法.接口等. 3. 如下为一个基本的注解例子: //注解中的成员变量非常像定义接口 public @int ...

  2. 深入学习JAVA注解-Annotation(学习过程)

    JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...

  3. 深入JAVA注解-Annotation(学习过程)

    JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...

  4. Java - 注解 (Annotation)

    Java - 注解 (Annotation)   一.基本的 Annotation     > 使用 Annotation 时要在其前面增加 @符号,并把该 Annotation 当成一个修饰符 ...

  5. Java注解Annotation(一)

    Java注解Annotation(一)——简介 这一章首先简单介绍一下注解,下一章会给出一个注解应用的DEMO. 1. 元注解 元注解的作用是负责注解其他的注解. JDK1.5中,定义了4个标准的me ...

  6. Java注解(Annotation)详解

    转: Java注解(Annotation)详解 幻海流心 2018.05.23 15:20 字数 1775 阅读 380评论 0喜欢 1 Java注解(Annotation)详解 1.Annotati ...

  7. Java注解Annotation与自定义注解详解

    Java注解简介 开发中经常使用到注解,在项目中也偶尔会见到过自定义注解,今天就来探讨一下这个注解是什么鬼,以及注解的应用场景和如何自定义注解. 下面列举开发中常见的注解 @Override:用于标识 ...

  8. java注解Annotation

    扯扯注解的蛋 为什么学习注解?学习注解有什么好处?学完能做什么? 1.能够读懂别人的代码,特别是框架相关的代码 2.让编程更加简洁,代码更加清晰 3.让别人高看你一眼 注解是java1.5引入的 概念 ...

  9. 秒懂,Java 注解 (Annotation)你可以这样学 - CSDN博客

    https://blog.csdn.net/briblue/article/details/73824058 文章开头先引入一处图片. 这处图片引自老罗的博客.为了避免不必要的麻烦,首先声明我个人比较 ...

随机推荐

  1. 单利 复利计算器程序1.0 2.0 3.0 [ 合 ] 之 C语言

    本程序用C语言编写~~~ 1.计算:本金为100万,利率或者投资回报率为3%,投资年限为30年,那么,30年后所获得的利息收入:按复利计算公式来计算就是:1,000,000×(1+3%)^30 1 v ...

  2. Pots 分类: 搜索 POJ 2015-08-09 18:38 3人阅读 评论(0) 收藏

    Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11885 Accepted: 5025 Special Judge D ...

  3. 山东理工大学第七届ACM校赛-经济节约 分类: 比赛 2015-06-26 10:34 19人阅读 评论(0) 收藏

    经济节约 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 由于经济紧张,某国国王决定减少一部分多余的士兵,这些士兵在边界都有各自的 ...

  4. Opencv中直线的表示方法

                               [blog算法原理]Opencv中直线的表示方法  一.问题的提出:​          在实际项目编写过程中,需要对直线(Line)进行特定的处 ...

  5. linux设备驱动编写_tasklet机制

    在编写设备驱动时, tasklet 机制是一种比较常见的机制,通常用于减少中断处理的时间,将本应该是在中断服务程序中完成的任务转化成软中断完成. 为了最大程度的避免中断处理时间过长而导致中断丢失,有时 ...

  6. Android:onNewIntent()触发机制及注意事项

    一.onNewIntent() 在IntentActivity中重写下列方法:onCreate onStart onRestart  onResume  onPause onStop onDestro ...

  7. ASCII字符表

  8. out 传值

    public void Out(out int a, out int b) {//out相当于return返回值 //可以返回多个值 //拿过来变量名的时候,里面默认为空值 a=1; b=2; } s ...

  9. pt-query-digest怎么分析慢查询日志分析数据

    在进行使用linux系统作为服务器的情况,那几需要进行对linux的服务器进行性能上数据进行抓取之后,就需要对数据中内容进行分析,看数据库中内容是否存在瓶颈上的问题,在进行获取到的数据的慢查日志,将使 ...

  10. [HDOJ5787]K-wolf Number(数位DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5787 题意:求[L,R]区间内的数字,使得所有长度为k的子数列内所有数位都不同. K<=5的所以 ...