Java 注解原理

时间:2021-01-10 00:36:33

下面来看看Java中注解是如何实现的

创建注解类Inter:

Java 注解原理

创建测试类Test:

Java 注解原理

在程序第二句设置断点,可以看到:

Java 注解原理

可以看到,注解的实例是一个动态代理类的对象.

要想查看这个动态代理类,可以在代码中加

System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

添加系统代理,将其导出为class文件

Java 注解原理

可以看到如下两个文件:

Java 注解原理

反编译$Proxy1.class,如下:

Java 注解原理

可以看到,动态代理类是我们定义的注解实现类,反编译Inner.class,如下:

Java 注解原理

可以看到,注解接口继承了java.lang.annotation.Annotation, 通过查看源码,该类源码如下:

Java 注解原理

可以看到, 该类下的方法都被$Proxy1动态代理类实现了.

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

那么, 代理类是如何处理方法的调用的呢?

我们知道, 动态代理方法的调用最终会传递给绑定的InvocationHandler实例的invoke方法处理。我们可以看看$Proxy1的源码

Java 注解原理

其中语句调用了父类的成员变量,其父类为Proxy, 查看该成员变量,如下:

Java 注解原理

可以看到, h对象类型就是InvocationHandler接口的某个实现类

我们在Proxy类的构造方法处设置断点:

Java 注解原理

通过断点可以查看h具体是哪个对象:

Java 注解原理

可以看到, 该动态代理类为AnnotationInvocationHandler对象, 查看该类的invoke方法如下:

Java 注解原理

其中的memberValues变量是以方法名为key,以变量为value的, 如下:

Java 注解原理

那么,这个memberValues变量是从哪来的呢?

Java 注解原理

可以看到,其是在构造函数中进行设置的.

反编译我们的Test类,看到:

Java 注解原理

所以中间有一个类,负责创建代理对象AnnotationInvocationHandler, 其将变量从常量池中取出并创建map, 进而创建代理对象, 这个类就是 AnnotationParser, 在此不细说了, 感兴趣的可以自行断点调试查看.


总结

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

Java 注解原理的更多相关文章

  1. java@ 注解原理与使用

    Java反射 java反射机制的定义: 在运行转态时(动态的)时. 对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够知道调用它的任意属性和方法 Class对象 java中用对 ...

  2. Java注解原理

    1. @interface不是接口是注解类,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节 2. @in ...

  3. 深入理解Java 注解原理

    *注解的用途 注解(Annotation)是JDK1.5引入的新特性,包含在java.lang.annotation包中,它是附加在代码中的一些元信息,将一个类的外部信息与内部成员联系起来,在编 译. ...

  4. Java Android 注解(Annotation) 及几个常用开源项目注解原理简析

    不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...

  5. java基础解析系列(六)---深入注解原理及使用

    java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer ja ...

  6. Java注解的基本概念和原理及其简单实用

      一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析 ...

  7. 认识下java注解的实现原理

    1,什么是注解 注解也叫元数据,例如常见的@Override和@Deprecated,注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包.类.接口.字段.方法参数.局部变量等进行注 ...

  8. java基础解析系列(六)---注解原理及使用

    java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及 ...

  9. java注解(Annotation)解析

    注解(Annotation)在java中应用非常广泛.它既能帮助我们在编码中减少错误,(比如最常见的Override注解),还可以帮助我们减少各种xml文件的配置,比如定义AOP切面用@AspectJ ...

随机推荐

  1. 2013MPD上海6.22 PM 陆宏杰:通往卓越管理的阶梯 & 6.23AM Ray Zhang 产品创新管理的十八般武艺

    MPD2天的内容,参加了5个课程,其中2个是管理的,分别是陆宏杰老师的<通往卓越管理的阶梯>和Ray Zhang大师的<产品创新管理的十八般武艺>.他们2个人都谈到了一个关于招 ...

  2. redis源码学习

    上帝禁区  http://blog.csdn.net/a600423444/article/details/8944601

  3. Linux服务器学习(一)

    一.首先连接服务器 下载一个windows下连接linux的ssh工具,我这里用的putty.一次填入HostName(主机名,可以是服务器域名也可以是对应的ip).Port(端口号默认为22).Co ...

  4. ThinkPhp 添加模型类

    ----------------------------------------------- <?phpnamespace app\common\model;use traits\model\ ...

  5. PHP设置凌晨时间戳

    这种需求应是很常见的,但一直没有时间整理. 一天可以领取2次奖励,今天领完了那就等明天再来. 这里面涉及到一个很重要的一点就是凌晨12点的时间戳,以前一直在前端去做判断.最近发现在后端用PHP获取凌晨 ...

  6. spring boot 访问jsp 弹出下载

    在pom.xml中加入以下jar 包 <!-- 引入Spring Boot 内嵌的Tomcat对jsp的解析包--><dependency> <groupId>or ...

  7. Java 时间相比较

    private String getRunTime() { String start = new Date.getTime(); String end= new Date.getTime(); lon ...

  8. 谈谈Flash图表中数据的采集

    一般来说flash中的数据是不能被现有技术很容易采集到的,但是也不能谈flash色变,要具体问题具体分析,有些flash是可以通过一些分析发现背后的数据.然后采集就变得很容易了. 具体案例:搜房房价走 ...

  9. JS实现背景图按时切换或者每次更新

    首先要有一个添加背景图片的div <div  id="myDiv"></div> css样式中添加背景tu图 body{height:100%;} #myD ...

  10. win10 解决&OpenCurlyDoubleQuote; &&num;39&semi;g&plus;&plus;&&num;39&semi; 不是内部或外部命令,也不是可运行的程序或批处理文件”的问题

    https://www.jianshu.com/p/9bffbaf12bed 2. 安装MinGW 将MinGW安装在D:\mingw文件夹下(可*选择,这里为之后添加环境变量作为范例) 安装好后选 ...