注解机制基础

为什么要学习注解

当我在学习java的框架时,会遇到大量的注解。尤其是在学习SpringBoot时,直接在启动类上加上一句 @SpringBootApplication注解就可以直接访问Controller这使得我感到非常神奇与震惊。这使得我对注解技术产生了好奇,便有了这篇博客。

注解的作用

如果说注释是写给人读的,以便理解代码。那么注解就是写个程序的。它像是一个标签一样贴在一个类、方法或字段上,它的作用是为当前读取注解的解析程序提供判断依据以及少量的运行信息。例如当解析程序读到@Test注解时就知道被标记的方法是一个待测试方法,又如当解析程序读到@Controller("/user/info")就会知道该方法是一个控制器以及该控制器的URL路径。需要知道的是注解不是程序的一部分,增加、修改、删除注解并不能改变程序的运行,注解只能影响该注解对应的注解解析程序。

什么是注解

注解的定义格式如下:

public @interface MyAnnotation {
    String getValue();
}

首先我们使用了 @interface来定义注解类型,这个定义的格式很像接口类型的定义,我猜想注解类型可能和接口本质上是一样的。于是我们可以用反编译的手段来验证我们的猜想。我们先在D盘下编写MyAnnotation.java文件内容就是上面的代码,用javac编译后,然后用javap进行反编译,得到的结果如下:
在这里插入图片描述可以看出进行反编译之后,上面的注解代码变成了实现Annotation接口的接口,所以我们得出注解的本质就是实现了Annotation接口的接口。
虽然说注解的本质就是接口,但是它却有一些奇怪的地方,例如:

@MyAnnotation(getValue =  "annotation on class")
public class Demo {
    @MyAnnotation(getValue = "annotation on field")
    public String name;
    @MyAnnotation(getValue = "annotation on method")
    public void hello(){}

它直接可以给方法赋值(虽然名字一样,但是可能getValue 不是 getValue(), 但是我不管这已经很奇怪了)并直接可以添加在类、方法和字段上。鉴于上面这种可以直接赋值的操作我们把String getValue()不叫方法而是叫做属性,给属性赋值,没毛病!虽然上面说了它的本质是接口,但由于注解的一些特殊性质,我们使用注解的情况下并不会把它当作接口来使用,所以我们就根据它的作用给它起了个见名知意的名字——注解。

注解的分类

jdk预定义注解
@Override: 检测被注解标记的方法是否继承自父类(接口)
@Deprecated:标记的内容,表示已过期
@SuppressWarnings:压制警告一般用法为@SuppressWarnings(“all”)
元注解
元注解这类注解是添加在注解上的注解,是用来约束其定义的注解的注解。
@Retention:用来描述被修饰的注解的生命周期。
@Target:用于指定被修饰的注解的适用范围,即被修饰的注解可以用来修饰哪些程序元素。
@Documented:用于指定被修饰的注解将被javadoc工具提取成文档。
@Inherited:用于指定被@Inherited修饰的注解具有继承性。
自定义注解
自定义注解就是我们根据自己的要求来定义注解,但是我们一般不会自定义注解,大多数情况都是使用框架里面的自定义注解来完成工作。如果是在自己定义注解的情况下,在定义好注解后,必须要编写对应的注解解析程序,调用解析程序来获取注解信息来完成任务,否则添加在类上的注解就没有任何作用的。

定义自定义注解的规则

元注解
public @interface 注解名称 {}

由于注解的本质是接口,那我们就可以在注解里面任意的定义抽象方法(注解里称属性),但是这些属性的返回值是有所限制的,它们只能是基本类型、String类型、枚举类型、注解类型或这几种类型的数组,我们也可以在属性的后面加上"default"关键字来设置默认值。


//自定义注解
//Target取值有TYPE、FIELD、METHOD等分别是注解可以添加在类、字段、和方法上
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
/*
Retention注解规定了注解保留到那个阶段,一般情况下为RUNTIME阶段
source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在 */
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    /*
    定义了属性,在使用时需要给属性赋值
     1.如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行赋值
     2.如果只有有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
     3.数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略
     */
    int getInt() default 1;
    String getValue() default "name";
    Annotation1 getAnnotation() default @Annotation1;
    //......
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值