注解的原理又是怎么一回事

栏目: Java · 发布时间: 8年前

内容简介:注解的原理又是怎么一回事

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内核设计剖析》已经在京东预售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。

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

欢迎关注:

注解的原理又是怎么一回事

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Data Mining

Web Data Mining

Bing Liu / Springer / 2011-6-26 / CAD 61.50

Web mining aims to discover useful information and knowledge from Web hyperlinks, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is not purely an ......一起来看看 《Web Data Mining》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试