Java注解Annotation学习
学习注解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生成的动态代理类的对象。
这个运行时生成的动态代理对象是可以导出到文件的,方法有两种
- 在代码中加入
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
- 在运行时加入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学习的更多相关文章
- Java注解Annotation学习笔记
一.自定义注解 1. 使用关键字 @interface 2. 默认情况下,注解可以修饰 类.方法.接口等. 3. 如下为一个基本的注解例子: //注解中的成员变量非常像定义接口 public @int ...
- 深入学习JAVA注解-Annotation(学习过程)
JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...
- 深入JAVA注解-Annotation(学习过程)
JAVA注解-Annotation学习 本文目的:项目开发过程中遇到自定义注解,想要弄清楚其原理,但是自己的基础知识不足以支撑自己去探索此问题,所以先记录问题,然后补充基础知识,然后解决其问题.记录此 ...
- Java - 注解 (Annotation)
Java - 注解 (Annotation) 一.基本的 Annotation > 使用 Annotation 时要在其前面增加 @符号,并把该 Annotation 当成一个修饰符 ...
- Java注解Annotation(一)
Java注解Annotation(一)——简介 这一章首先简单介绍一下注解,下一章会给出一个注解应用的DEMO. 1. 元注解 元注解的作用是负责注解其他的注解. JDK1.5中,定义了4个标准的me ...
- Java注解(Annotation)详解
转: Java注解(Annotation)详解 幻海流心 2018.05.23 15:20 字数 1775 阅读 380评论 0喜欢 1 Java注解(Annotation)详解 1.Annotati ...
- Java注解Annotation与自定义注解详解
Java注解简介 开发中经常使用到注解,在项目中也偶尔会见到过自定义注解,今天就来探讨一下这个注解是什么鬼,以及注解的应用场景和如何自定义注解. 下面列举开发中常见的注解 @Override:用于标识 ...
- java注解Annotation
扯扯注解的蛋 为什么学习注解?学习注解有什么好处?学完能做什么? 1.能够读懂别人的代码,特别是框架相关的代码 2.让编程更加简洁,代码更加清晰 3.让别人高看你一眼 注解是java1.5引入的 概念 ...
- 秒懂,Java 注解 (Annotation)你可以这样学 - CSDN博客
https://blog.csdn.net/briblue/article/details/73824058 文章开头先引入一处图片. 这处图片引自老罗的博客.为了避免不必要的麻烦,首先声明我个人比较 ...
随机推荐
- Codeforces Round #336 Marbles
E. Marbles time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard in ...
- Emag eht htiw Em Pleh 分类: POJ 2015-06-29 18:54 10人阅读 评论(0) 收藏
Emag eht htiw Em Pleh Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2937 Accepted: ...
- Robotium中定位Android客户端疑难元素
对于没有id,没有text,只有一个图标的疑难元素(ImageView),应该如何定位呢?拿人人网个人主页的设置按钮举例: 我最终是通过定位页面上可以定位到的其他元素,然后通过其他元素与疑难元素相对坐 ...
- WinFormd多窗体 菜单和工具栏:
一.多窗体 1.哪个是主窗体 主窗体就是如果关掉这个窗体,程序就会退出的那个窗体1问题:主窗体隐藏了,关闭其它窗体后,没有将主窗体显示/关闭,那么程序就关不上了 办法:构造函数传值,将窗体传到另一个窗 ...
- AJAX和jQuery Ajax总结
AJAX全称为“Asynchronous JavaScript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用,改善用户体验,实现无刷新效果的技术. 使用AJAX的优 ...
- 获取或者设置时,无后缀和A后缀和W后缀的区别
SetWindowTextW表示设置的字符串是WCHAR (双字节字符 )SetWindowTextA表示设置的字符串是CHAR (单字节字符 )SetWindowText表示设置的字符串是自动匹配当 ...
- SqlSever基础 ltrim函数 除去字符串左边的空格,右边的中间的不管
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- C# Eval()和Bind()
Eval( " ")和Bind( " ") 这两种一个单向绑定,一个双向绑定,bind是双向绑定,但需数据源支持ASP.NET 2.0改善了模板中的数据绑定 ...
- 【leetcode❤python】350. Intersection of Two Arrays II
#-*- coding: UTF-8 -*- class Solution(object): def intersect(self, nums1, nums2): ...
- 取消mod_sofia的呼叫鉴权
FreeSWITCH中默认的SIP呼叫是要鉴权的,流程如下. 终端 FreeSWITCH A -----Invite------> FS A <----Trying------ FS A ...