栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java和Spring注解(二)——深入理解注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java和Spring注解(二)——深入理解注解

注重版权,若要转载烦请附上作者和链接

作者:Joshua_yi

链接:https://blog.csdn.net/weixin_44984664/article/details/122088060

文章目录
    • 一、注解
      • (一)注解的作用
      • (二)源码解读
    • 二、基本元注解与注解解析
      • (一)ElementType
      • (二)RetentionPolicy
      • (三)@documented
      • (四)@Inherited
      • (五)@Retention
      • (六)@Target
      • (七)@Repeatable
      • 三、总结
      • 参考文档


一、注解

注解Annotation,也叫元数据

(一)注解的作用

我们可以从注解作用的对象上分析注解的作用

public enum ElementType {
    
    TYPE,

    
    FIELD,

    
    METHOD,

    
    PARAMETER,

    
    CONSTRUCTOR,

    
    LOCAL_VARIABLE,

    
    ANNOTATION_TYPE,

    
    PACKAGE,

    
    TYPE_PARAMETER,

    
    TYPE_USE
}
  • TYPE:注解可以作用在类、接口(包括其他注解),枚举类型上
  • ANNOTATION_TYPE:其他注解上
  • FIELD:可以作用在类的属性上
  • METHOD:方法上(不包括构造方法)
  • CONSTRUCTOR:构造方法上
  • PARAMETER:方法参数上
  • LOCAL_VARIABLE:局部变量上
  • PACKAGE:作用在包上,具体用法可以参考https://blog.csdn.net/weixin_38321868/article/details/118942209
  • TYPE_PARAMETER :表示该注解能写在类型参数的声明语句中。(eg:泛型声明)
  • TYPE_USE:表示注解可以任何用到类型的地方使用,无处不在的注解,可以让编译器执行更严格的代码检查,从而提高程序的健壮性。比如可以应用在以下地方
    • 创建对象(用 new 关键字创建)
    • 类型转换
    • 使用 implements 实现接口
    • 使用 throws 声明抛出异常
public class Solution {
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_PARAMETER)
    public @interface isParam {
    }

    public <@isParam T> void fun1(T ob) {
        System.out.println(ob);
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    public @interface isNotNull {
    }

    public <@isNotNull T> void fun2(@isNotNull T ob) throws @isNotNull Exception {
        String s = (@isNotNull String) "11111";
        System.out.println(ob);
    }
}

注解可以对这些程序元素添加一些额外的信息,这些信息可以用于之后的一些操作。
根据一个注解是否包含成员函数,可以将注解大致分为两类
标记注解:没有成员变量的Annotation被称为标记。这种Annotation仅用自身的存在与否来为我们提供信息,例如@override等。
元数据注解:包含成员变量的Annotation。因为它们可以接受更多的元数据,因此被称为元数据Annotation。 成员以无参数的方法的形式被声明,其方法名和返回值定义了该成员变量的名字和类型。

PS:注解没有成员变量,只有方法Annotation的成员变量在Annotation定义中以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。
可以使用default关键字为成员变量指定默认值

(二)源码解读

注解相关源码在java.lang.annotation包下

  • Annotation 是所有注解继承的接口,这也就是为什么说,接口底层是一个接口。
    (定义了@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口)
  • AnnotationFormatError继承自Error,当注释解析器从类文件读取注释并确定该注解有错误时抛出
  • AnnotationTypeMismatchException继承自RuntimeException,表示程序试图访问注释的某个元素,该注释的类型在编译(或序列化)后发生了更改,这时候抛出该异常
  • IncompleteAnnotationException继承自RuntimeException,表示程序试图访问注释类型的元素,该元素是在注释被编译(或序列化)后添加到注释类型定义中的,也就是找不到该注解中的一些成员变量。
  • ElementType 指定注解在Java程序中注释可能出现的语法位置。
  • RetentionPolicy 描述了保留注解的策略,源码级、字节码、运行时
  • @Native 修饰类属性,表示这个变量可以被本地代码引用,常常被代码生成工具使用。
  • 其他五个注解都可以修饰其他注解,被称为元注解。(meta-Annotation)

PS:看了各种官方文档,还没有找到对这个meta-Annotation的准确定义。
只知道可以作用在其他注解上的注解叫做元注解。为了区别于自己定义的元注解,以下统称为基本元注解

二、基本元注解与注解解析

在说明该五个基本元注解之前,需要对ElementType(前文已经有相关阐述)和RetentionPolicy进行讲解

(一)ElementType

见前文

(二)RetentionPolicy
public enum RetentionPolicy {
    
    SOURCE,

    
    CLASS,

    
    RUNTIME
}

  • RetentionPolicy.SOURCE:表明注解会被编译器丢弃,字节码中不会带有注解信息。一般用于需要在编译器层面就可以发现的问题。比如@override就是代码级别可见,与编译器相结合来检查问题。

  • RetentionPolicy.CLASS:表明注解会被写入字节码文件,是@Retention的默认值。简单来说,其自定义注解解析需要实现AbstractProcessor的process()方法。基本使用可以参考该文章 java注解之编译时注解RetentionPolicy.CLASS 基本用法

  • RetentionPolicy.RUNTIME:表明注解会被写入字节码文件,并且能够被JVM 在运行时获取通过反射的方式解析到。

反射常用到的函数如下

  • T getAnnotation(Class) : 获得当前对象的指定的注解。
  • Annotation[] getAnnotations() X: 获得当前对象的所有注解
  • boolean isAnnotationPresent(annotationClass): 当前对象是否有注解。

PS:定义了一个注解之后,只是一个空的定义,需要通过定义注解解析来赋予其实在的意义。常用的自定义的注解解析,是通过反射来进行相关操作的,也就是说需要指定注解的Retention到RUNTIME。

(三)@documented
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface documented {
}

在用javadoc命令生成API文档后,文档里会出现该注解说明

(四)@Inherited
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

@Inherited 表示该注解具有继承性。
即如果一个使用了@Inherited 修饰的annotation 类型被用于一个class,则这个annotation 将被用于该class 的子类。

(五)@Retention
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    
    RetentionPolicy value();
}

指定注解生命周期RetentionPolicy
上面已经详细进行了解释

(六)@Target
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    
    ElementType[] value();
}

指定注解作用对象ElementType
上面已经详细进行了解释

(七)@Repeatable
@documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
    
    Class value();
}

@Repeatable是JDK1.8新加入的,它表示在同一个位置重复相同的注解。在没有该注解前,要想在同一个类型上使用相同的注解需要指定value为数组。
eg:

@FilterPath("/update")
@FilterPath("/add")
public class A {}
三、总结

以上部分结合源码对Java注解进行了较为详细的阐述。重点在于注解、基本元注解以及相关使用场景做了解释。很多部分仅代表自己的观点,如有错误还请各位指正~~

参考文档

https://blog.csdn.net/chenliguan/article/details/78304025
https://www.jianshu.com/p/613e3b1bd842
https://blog.csdn.net/sjh66655/article/details/112901868
https://blog.csdn.net/xtho62/article/details/113816008
https://blog.csdn.net/u014207606/article/details/52291951

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/681415.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号