JAVA 注解机制【七日打卡】

645 阅读3分钟

不知道大家在平时用到注解的频率多不多,注解对我们的帮助很大,能为我们节省很多工作。最直接的就是可以代替配置文件的功能,无论是基本的servlet还是常用的三大框架,里面都使用了注解,并且逐渐的代替了原本繁琐的配置,大大提高了编码效率。

随着注解使用的越来越频繁,我们对底层实现的了解越来越少,所以在这一章我们来好好了解一下注解是怎么实现的。

首先注解是什么?通俗的意思是为程序的元素(类、方法、成员变量)加上更直观更明了的说明(比如 @Override),这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或框架使用的。

他的基本原理和流程就是:通过调用Java的反射机制相关API来访问annotation信息。首先加载使用注解的类,得到class类。然后再得到类相应的方法,成员变量。得到变量后调用相应的类、方法、成员变量的对象的isAnnotationPresent方法判断是否使用了注解。之后通过调用相应的类、方法、成员变量的的getAnnotation方法得到相应的注解的对象。接下来我们就可以操作注解对象完成相应的逻辑。

我们来熟悉一下注解的基本结构:

最上面的一部分注解叫做元注解,就是注解的注解。@Target 指的是这个注解可以用在什么地方。他的参数可以有如下:

接着就是@Retention了,它指的是这个注解的生命周期。他的参数可以包括SOURCE、CLAS和 RUNTIME。

  • SOURCE:如果Retention成员取值为SOURCE,表明该注解只存在源代码当中,在编译的时候会被编译器丢掉。如重写方法时,方法上面会有@Override注解,这个注解就是source类型的。
  • CLASS:表示注解会被存到字节码文件.class中,但是虚拟机载入class文件的时候不会将注解导入,因此运行时无法得到。如果不在注解中使用Retention指定,则默认的保留策略为CLASS。
  • RUNTIME:不仅保存到class文件,还会被虚拟机载入内存,因此在运行的时候可以通过反射得到并且使用这些注解。我们待会的例子就是以RUNTIME为例。
  • 而 @Inherited和@Documented表达的意思比较简单:@Inherited 表示子类可以继承父类的注解(有空会细讲);@Documented 表示生成doc文档的时候会包含这个注解。
  • “public @interface Anno”则是定义注解的关键字以及名字。接下来就是一些成员变量了,注意:这里是变量,不要以为有个括号就是方法了。使用方式是这样的@Anno(name="wizard",age=12) 。

注意:成员变量只能是基本类型、String、class、enum、Annotation和以上类型的数组,而且必须是无参数、不能抛出异常。