博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
注解的原理又是怎么一回事
阅读量:7209 次
发布时间:2019-06-29

本文共 2280 字,大约阅读时间需要 7 分钟。

Java内置的注解以及自定义一个注解大家都比较熟悉的了,现在来看看注解实现的原理,看看Java的体系下面是如何对注解的支持的。

在讨论前先看一个自定义注解的例子,自定义实现这样一个注解:通过@Test向某类注入一个字符串,通过@TestMethod向某个方法注入一个字符串。

① 创建Test注解,声明作用于类并保留到运行时,默认值为default。

@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface Test {    String value() default "default";}

② 创建TestMethod注解,声明作用于方法并保留到运行时。

@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface TestMethod {    String value();}

③测试类,运行后输出default和tomcat-method两个字符串,因为@Test没有传入值,所以输出了默认值,而@TestMethod则输出了注入的字符串。

@Test()public class AnnotationTest {    @TestMethod("tomcat-method")    public void test(){    }    public static void main(String[] args){        Test t = AnnotationTest.class.getAnnotation(Test.class);        System.out.println(t.value());        TestMethod tm = null;        try {            tm = AnnotationTest.class.getDeclaredMethod("test",null).getAnnotation(TestMethod.class);        } catch (Exception e) {            e.printStackTrace();        }        System.out.println(tm.value());    }}

对于注解Test,如果对AnnotationTest类进行注解,则运行时可以通过AnnotationTest.class.getAnnotation(Test.class)获取注解声明的值,从上面的句子就可以看出,它是从class结构中获取出Test注解的,所以肯定是在某个时候注解被加入到class结构中去了。

@Test("test") public class AnnotationTest {     public void test(){     } }

从java源码到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里面的属性值。

这里可能会有疑问,Test注解对象是什么?其实注解被编译后的本质就是一个继承Annotation接口的接口,所以@Test其实就是public interface Test extends Annotation,当我们通过AnnotationTest.class.getAnnotation(Test.class)调用时,JDK会通过动态代理生成一个实现了Test接口的对象,并把将RuntimeVisibleAnnotations属性值设置进此对象中,此对象即为Test注解对象,通过它的value()方法就可以获取到注解值。

Java注解实现机制的整个过程如上面所示,它的实现需要编译器和JVM一起配合。

====广告时间,可直接跳过====

鄙人的新书《Tomcat内核设计剖析》已经在京东预售了,有需要的朋友可以到 进行预定。感谢各位朋友。

=========================

欢迎关注:

转载地址:http://tqgum.baihongyu.com/

你可能感兴趣的文章
浅谈Vue内置component组件的应用场景
查看>>
js发布订阅,vue里面也需要
查看>>
【LocustPlus序】漫谈服务端性能测试
查看>>
顺序程序代码分析
查看>>
MaxCompute,基于Serverless的高可用大数据服务
查看>>
flex布局
查看>>
React通过redux-persist持久化数据存储
查看>>
hibernate实体监听器
查看>>
怎么解决在微信中不能直接下载APP(APK)的方案
查看>>
你真的懂switch吗?聊聊switch语句中的块级作用域
查看>>
JS基础(对象创建,构造函数、原型、实例之间关系,继承方式)
查看>>
在Kubernetes集群上部署和管理JFrog Artifactory
查看>>
Prettier+VScode 治好你的代码洁癖
查看>>
macOS安装配置MySQL
查看>>
环形百分比控件iantoo.percent()
查看>>
专访阿里数据库备份专家 教你pick最有效的备份系统
查看>>
【刷算法】判断链表是否有环以及返回入环节点
查看>>
XXL-CONF v1.5.0 发布,分布式配置中心
查看>>
Java 操作符(3)
查看>>
教你springboot maven多模块如何部署
查看>>