最近在学习 Spring Boot,发现真的是一个靠注解搭起来的框架,Spring 从使用 XML 到现在使用注解,大概是终于发现绝大多数人所写的项目,都不需要 XML 的松耦合,快速上线、快速丢弃、快速接手,在一切都要求快的互联网公司里,XML 这样的松耦合浪费太多的学习成本了,划不来。
之前一直没有系统学习过 Java 的注解,学习起 Spring Boot 来总是用得不明所以,想想还是从基础学起,方不至于浪费大量的时间去查找 Spring Boot 各个注解的使用文档。
Java 的注解,实际上包含三方面的内容,一个是 Java 注解本身的定义,一个是 Java 注解的使用,一个是如何利用 Java 的反射功能实现功效。本文也将从这三个方面逐一讲解,主要参考文章 JAVA 注解的基本原理 和 Java 语法标准。
Java 内置了许多的注解,在 Java Annotation 可以找到内置的所有注解,我们最常见的注解应该是 @Deprecated,一旦一个方法使用了这个注解,别人此后再使用这个方法时,就会提示这个方法已经被废弃了,建议不再使用。
那 @Deprecated 到底是怎么定义的呢?它还能用在什么地方?JDK 是如何在编译的时候遇到这个注解就马上发出一个提示的呢?带着这些疑问,一步一步学习 Java 的注解。
一、如何创建一个注解
所有的注解本身都继承于 java.lang.annotation.Annotation, 每一个注解本身就是一个 interface,但是注解这种 interface 有其特殊性,所以,所有的注解都是这样定义的:
publice @interface xxxx {}
@Deprecated 的实现代码如下:
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
多了 @Documented,@Retention,@Target 三个注解,这三个注解分别是什么呢?又有什么作用呢?
用于方法的方法,叫做元方法,所以用于注解的注解,就叫做元注解,这三个都是 JDK 提供的元注解。
- @Documented 标记这个注解 @Deprecated 将会出现在 Java Doc 之中
- @Rentention 标明这个注解的生命周期,RententionPolicy 里面定义了三种生命周期,分别是 SOURCE,CLASS,RUNTIME 三种,SOURCE 表示在编译阶段抛弃,CLASS 表示会被记录到 class 文件里面,但不会出现在 vm 里面运行,RUNTIME 表示在运行期里面存活。
- @Target 表示这个注解可以用在何处,比如 @Deprecated 的定义,表明它可以用在构造函数,字段,本地变量,方法,包,参数,类
@Deprecated
public class TestDeprecated {
@Deprecated
public String name;
@Deprecated
public TestDeprecated(String name){ }
@Deprecated
public String getName() {return name;}
public void testDeprecatedParam(@Deprecated String name, String sex){
@Deprecated
String test = "test";
System.out.println(name + sex + test);
}
}
如上是 @Deprecated 在类、字段、构造函数、方法、参数和本地变量的使用方式。不过本地变量和参数的 @Deprecated 似乎是不起作用的。另外,package 级别的注解使用,需要使用 package-info.java, 比如 package-info.java 文件如下:
@Deprecated
package com.shahuwang;
这样子就标记了整个包都是要废弃的了。
目前 Java 10 提供了 @Documented,@Inherited,@Native,@Repeatable,@Retention,@Target 共六个元注解,除了上面已讲解过的三个,剩余三个的用途:
-
@Inherited 表示使用了它的注解,再用到类上面时,可被子类继承此注解。
@Inherited publice @interface Test{} @Test public class Parent{} public class Child extends Parent{}
如上,Child 类也继承了 @Test 这个注解,可以使用它的功能。
- @Native 表示定义常量值的字段可以被 native 代码引用,当 native 代码和 java 代码都需要维护相同的常量时,如果 java 代码使用了 @Native 标志常量字段,可以通过工具将它生成 native 代码的头文件。目前对 Java 的 native 代码研究比较少,后面再对它进行研究
- @Repeatable 表示注解可以重复使用,是 Java 8 引进的特性。之前注解只能在同一个地方用一次,用了 @Repeatable,注解就可以在同一个地方使用多次了,可以参考这篇文章 https://blog.csdn.net/aitangy…