下面来看看Java中注解是如何实现的
创建注解类Inter:
创建测试类Test:
在程序第二句设置断点,可以看到:
可以看到,注解的实例是一个动态代理类的对象.
要想查看这个动态代理类,可以在代码中加
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
添加系统代理,将其导出为class文件
可以看到如下两个文件:
反编译$Proxy1.class,如下:
可以看到,动态代理类是我们定义的注解实现类,反编译Inner.class,如下:
可以看到,注解接口继承了java.lang.annotation.Annotation, 通过查看源码,该类源码如下:
可以看到, 该类下的方法都被$Proxy1动态代理类实现了.
到此处,我们已经知道Inner注解(接口)是一个继承了Annotation接口的特殊接口,而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1,该类就是Inner注解(接口)的具体实现类。
那么, 代理类是如何处理方法的调用的呢?
我们知道, 动态代理方法的调用最终会传递给绑定的InvocationHandler实例的invoke方法处理。我们可以看看$Proxy1的源码
其中语句调用了父类的成员变量,其父类为Proxy, 查看该成员变量,如下:
可以看到, h对象类型就是InvocationHandler接口的某个实现类
我们在Proxy类的构造方法处设置断点:
通过断点可以查看h具体是哪个对象:
可以看到, 该动态代理类为AnnotationInvocationHandler对象, 查看该类的invoke方法如下:
其中的memberValues变量是以方法名为key,以变量为value的, 如下:
那么,这个memberValues变量是从哪来的呢?
可以看到,其是在构造函数中进行设置的.
反编译我们的Test类,看到:
所以中间有一个类,负责创建代理对象AnnotationInvocationHandler, 其将变量从常量池中取出并创建map, 进而创建代理对象, 这个类就是 AnnotationParser, 在此不细说了, 感兴趣的可以自行断点调试查看.
总结
注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。
Java 注解原理的更多相关文章
-
java@ 注解原理与使用
Java反射 java反射机制的定义: 在运行转态时(动态的)时. 对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够知道调用它的任意属性和方法 Class对象 java中用对 ...
-
Java注解原理
1. @interface不是接口是注解类,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节 2. @in ...
-
深入理解Java 注解原理
*注解的用途 注解(Annotation)是JDK1.5引入的新特性,包含在java.lang.annotation包中,它是附加在代码中的一些元信息,将一个类的外部信息与内部成员联系起来,在编 译. ...
-
Java Android 注解(Annotation) 及几个常用开源项目注解原理简析
不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...
-
java基础解析系列(六)---深入注解原理及使用
java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer ja ...
-
Java注解的基本概念和原理及其简单实用
一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析 ...
-
认识下java注解的实现原理
1,什么是注解 注解也叫元数据,例如常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包.类.接口.字段.方法参数.局部变量等进行注 ...
-
java基础解析系列(六)---注解原理及使用
java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及 ...
-
java注解(Annotation)解析
注解(Annotation)在java中应用非常广泛.它既能帮助我们在编码中减少错误,(比如最常见的Override注解),还可以帮助我们减少各种xml文件的配置,比如定义AOP切面用@AspectJ ...
随机推荐
-
2013MPD上海6.22 PM 陆宏杰:通往卓越管理的阶梯 &; 6.23AM Ray Zhang 产品创新管理的十八般武艺
MPD2天的内容,参加了5个课程,其中2个是管理的,分别是陆宏杰老师的<通往卓越管理的阶梯>和Ray Zhang大师的<产品创新管理的十八般武艺>.他们2个人都谈到了一个关于招 ...
-
redis源码学习
上帝禁区 http://blog.csdn.net/a600423444/article/details/8944601
-
Linux服务器学习(一)
一.首先连接服务器 下载一个windows下连接linux的ssh工具,我这里用的putty.一次填入HostName(主机名,可以是服务器域名也可以是对应的ip).Port(端口号默认为22).Co ...
-
ThinkPhp 添加模型类
----------------------------------------------- <?phpnamespace app\common\model;use traits\model\ ...
-
PHP设置凌晨时间戳
这种需求应是很常见的,但一直没有时间整理. 一天可以领取2次奖励,今天领完了那就等明天再来. 这里面涉及到一个很重要的一点就是凌晨12点的时间戳,以前一直在前端去做判断.最近发现在后端用PHP获取凌晨 ...
-
spring boot 访问jsp 弹出下载
在pom.xml中加入以下jar 包 <!-- 引入Spring Boot 内嵌的Tomcat对jsp的解析包--><dependency> <groupId>or ...
-
Java 时间相比较
private String getRunTime() { String start = new Date.getTime(); String end= new Date.getTime(); lon ...
-
谈谈Flash图表中数据的采集
一般来说flash中的数据是不能被现有技术很容易采集到的,但是也不能谈flash色变,要具体问题具体分析,有些flash是可以通过一些分析发现背后的数据.然后采集就变得很容易了. 具体案例:搜房房价走 ...
-
JS实现背景图按时切换或者每次更新
首先要有一个添加背景图片的div <div id="myDiv"></div> css样式中添加背景tu图 body{height:100%;} #myD ...
-
win10 解决“ &#39;g++&#39; 不是内部或外部命令,也不是可运行的程序或批处理文件”的问题
https://www.jianshu.com/p/9bffbaf12bed 2. 安装MinGW 将MinGW安装在D:\mingw文件夹下(可*选择,这里为之后添加环境变量作为范例) 安装好后选 ...