Java高级特性-注解:Spring的注解是怎么回事?

在 Spring 中,大家会经常用到各种注解。在加上这些注解后,我们的代码就有了很多神奇的功能。

比如,下面这个类只用了两个注解:@Controller@RequestMapping,你就能在浏览器上访问 index() 方法。

@Controller
@RequestMapping("/")
public class IndexController {

    @RequestMapping(value = "index")
    public String index() {
        return "index";
    }

就这么简单的功能,你如果用 Java 自带的 Servlet,要写的代码最少也会翻倍。

这就是注解的威力。

什么是注解?

注解相当于给代码贴标签,你可以写代码来读取这些标签信息,做特殊的处理,从而实现更丰富的功能。

比如,下面这个例子,方法加上了@Override注解,Java 就会做出处理,覆盖父类toString()方法。

public class User {
    // 覆盖父类的toString() 方法
    @Override
    public String toString() {
        return "这是一个用户对象";
    }
}

注解大致分成三类:JDK内置注解、第三方注解、自定义注解。

JDK内置注解,就是JDK自带的注解。比如,@Override表示用子类的方法覆盖父类的方法。

public class UserOrderNoGen extends OrderNoGen {
    // 这个注解表示:覆盖父类的 genOrderNo() 方法
    @Override
    public String genOrderNo() {
        // 省略无数代码
    }
}

第三方注解,就是第三方框架提供的注解。比如,Spring 框架提供的@Controller@RequestMapping,我重新贴下文章开头的例子。

@Controller
@RequestMapping("/")
public class IndexController {

    @RequestMapping(value = "index")
    public String index() {
        return "index";
    }
}

自定义注解,就是我们自己写的注解。比如,我创建了一个注解@ExcelField,可以放在类上,表示这个类是 Excel 导出模板。

// Excel导出模板
public @interface ExcelField {
    // 省略无数代码
}

// 用户信息表
@ExcelField
public class UserInfoField {
    // 省略无数代码
}

此外,注解的级别非常高,和类、接口、枚举是同一级别的,有自己的一套写法。我们先看看注解怎么写吧~

写注解-加上元注解

所谓元注解,就是加在注解上的注解。

如果你要自定义注解,有两个元注解非常重要,几乎是必须加上的,分别是:@Target@Retention

@Target是限制注解的使用范围,表示这个注解能用在什么地方,它的取值范围在枚举 ElementType 里。 如果用@Target来限制注解的使用范围,那么超出这个范围,代码就会报错。

Java高级特性-注解:Spring的注解是怎么回事?_第1张图片

当然,你也可以不加@Target注解,这代表不限制注解的使用范围,你可以随便放,不会报错。

Java高级特性-注解:Spring的注解是怎么回事?_第2张图片

@Retention是注解的保留策略,它的取值范围在枚举 RetentionPolicy 里。 注解的保留策略有 3 种,分别是:SOURCE、CLASS、RUNTIME。

SOURCE:注解只在源码中出现,在经过编译后,注解会被丢弃,不会出现在 class 文件中;
CLASS:经过编译后,注解会保留在 class 文件中,但在 JVM 加载时会忽略注解;
RUNTIME:在 JVM 加载时,注解会被加载到 JVM 内存,所以使用反射来读取注解;

但说实话,在这三种保留策略中,SOURCE 策略还不如多写两行注释;CLASS 策略就是让你看看,没太大作用;只有 RUNTIME 模式,才能真正发挥注解的作用。

注解的结构-成员变量

注解支持成员变量,成员变量可以用这些类型:

  1. 基本数据类型
  2. String
  3. 枚举类型
  4. 注解类型
  5. Class类型
  6. 以上类型的一维数组

这块我们没必要花太多时间,在用到的时候,再回来瞄一下就好。

最后,我们来看下注解是怎么起作用的。

注解是怎么起作用的?

注解想发挥作用,有三个要素:定义、使用、读取。

如果你用的是JDK内置注解,或者是第三方注解,那么只要使用就行,不用管定义和执行。

比如,Spring 框架会把注解类、读取注解的代码藏起来,我们只要会用就行,不用管太多。你可以看下面这个例子。

// 使用 Spring 的注解,把这个类交给 Spring 容器管理
@Service
public class UserService {

}

相比起来,自定义注解会更加复杂。自定义注解想发挥作用,我们需要自己定义注解,自己使用注解,最后再写代码读取。

有时候,我们要用自定义注解,才能实现一些功能。

比方说,这是一个 Excel 导出的功能,你得先创建注解@ExcelField,然后把@ExcelField加到模板类的成员变量上,最后用工具类ExcelExporter来导出 excel 表格。

Java高级特性-注解:Spring的注解是怎么回事?_第3张图片

在注解的三要素中,定义注解是比较容易的,但使用、读取注解跟业务绑定很深,一两句话很难讲清楚,我们以后会结合实际案例来看。

写在最后

注解相当于给代码贴标签,你可以写代码来读取这些标签信息,做特殊的处理,从而实现更丰富的功能。

不过,注解想发挥作用,有三个要素:定义、使用、读取。但我们很少试过自定义注解,没有经历过定义—>使用—>读取的过程,就搞不清楚注解是怎么回事,更别提用好注解了。

换句话说,想要用好注解,你得看更多的实际案例,写更多的代码。

你可能感兴趣的:(java)