广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >如何理解Java注解和注解解析器
  • 224
分享到

如何理解Java注解和注解解析器

2024-04-02 19:04:59 224人浏览 薄情痞子
摘要

这篇文章主要讲解了“如何理解Java注解和注解解析器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Java注解和注解解析器”吧!什么是元数据(met

这篇文章主要讲解了“如何理解Java注解和注解解析器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Java注解和注解解析器”吧!

如何理解Java注解和注解解析器

什么是元数据(metadata)

元数据由metadata译来,所谓的元数据就是“关于数据的数据”,更通俗的说就是描述数据的数据,对数据及信息资源的描述性信息.比如说一个文本文件,有创建时间,创建人,文件大小等数据,这都可以理解为是元数据.

在java中,元数据以标签的形式存在java代码中,它的存在并不影响程序代码的编译和执行,通常它被用来生成其它的文件或运行时知道被运行代码的描述信息。java当中的javadoc和注解都属于元数据.

什么是注解(Annotation)?

注解是从java 5.0开始加入,可以用于标注包,类,方法,变量等.比如我们常见的@Override,再或者Android源码中的@hide,@systemapi,@privateApi等

对于@Override,多数人往往都是知其然而不知其所以然,今天我就来聊聊Annotation背后的秘密,开始正文.

元注解就是定义注解的注解,是java提供给我们用于定义注解的基本注解.在java.lang.annotation包中我们可以看到目前元注解共有以下几个:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. @Retention

  3. @Target

  4. @Inherited

  5. @Documented

  6. @interface

下面我们将集合@Override注解来解释着5个基本注解的用法.

@interface

@interface是java中用于声明注解类的关键字.使用该注解表示将自动继承java.lang.annotation.Annotation类,该过程交给编译器完成.

因此我们想要定义一个注解只需要如下做即可,以@Override注解为例

public @interface Override { }
需要注意:在定义注解时,不能继承其他注解或接口
@Retention

@Retention:该注解用于定义注解保留策略,即定义的注解类在什么时候存在(源码阶段 or 编译后 or 运行阶段).该注解接受以下几个参数: RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME ,其具体使用及含义如下:

如何理解Java注解和注解解析器

来看一下@Override注解的保留策略:

@Retention(RetentionPolicy.SOURCE) public @interface Override { }

这表明@Override注解只在源码阶段存在,javac在编译过程中去去掉该注解.

@Target

该注解用于定义注解的作用目标,即注解可以用在什么地方,比如是用于方法上还是用于字段上,该注解接受以下参数:

如何理解Java注解和注解解析器

以@Override为例,不难看出其作用目标为方法:

@Target(ElementType.METHOD) public @interface Override { }

到现在,通过@interface,@Retention,@Target已经可以完整的定义一个注解,来看@Override完整定义:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }
@Inherited

默认情况下,我们自定义的注解用在父类上不会被子类所继承.如果想让子类也继承父类的注解,即注解在子类也生效,需要在自定义注解时设置@Inherited.一般情况下该注解用的比较少.

@Documented

该注解用于描述其它类型的annotation应该被javadoc文档化,出现在api doc中.

比如使用该注解的@Target会出出现在api说明中.

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

借助@Interface,@Target,@Retention,@Inherited,@Documented这五个元注解,
我们就可以自定义注解了,其中前三个注解是任何一个注解都必备具备的.

自定义注解

格式:

public @interface 注解名 {定义体}

定义体就是方法的集合,每个方法实则是声明了一个配置参数.方法的名称作为配置参数的名称,方法的返回值类型就是配置参数的类型.和普通的方法不一样,可以通过default关键字来声明配置参数的默认值.

需要注意:

此处只能使用public或者默认的defalt两个权限修饰符

配置参数的类型只能使用基本类型(byte,boolean,char,short,int,long,float,double)和String,Enum,Class,annotation

对于只含有一个配置参数的注解,参数名建议设置中value,即方法名为value

配置参数一旦设置,其参数值必须有确定的值,要不在使用注解的时候指定,要不在定义注解的时候使用default为其设置默认值,对于非基本类型的参数值来说,其不能为null.

像@Override这样,没有成员定义的注解称之为标记注解.

注解处理器

上面我们已经学会了如何定义注解,要想注解发挥实际作用,需要我们为注解编写相应的注解处理器.根据注解的特性,注解处理器可以分为运行时注解处理和编译时注解处理器.运行时处理器需要借助反射机制实现,而编译时处理器则需要借助APT来实现.

无论是运行时注解处理器还是编译时注解处理器,主要工作都是读取注解及处理特定注解,从这个角度来看注解处理器还是非常容易理解的.

注解处理器是(Annotation Processor)是javac的一个工具,用来在编译时扫描和编译和处理注解(Annotation)。你可以自己定义注解和注解处理器去搞一些事情。一个注解处理器它以Java代码或者(编译过的字节码)作为输入,生成文件(通常是java文件)。这些生成的java文件不能修改,并且会同其手动编写的java代码一样会被javac编译。看到这里加上之前理解,应该明白大概的过程了,就是把标记了注解的类,变量等作为输入内容,经过注解处理器处理,生成想要生成的java代码。

运行时注解处理器(不建议使用)

熟悉java反射机制的同学一定对java.lang.reflect包非常熟悉,该包中的所有api都支持读取运行时Annotation的能力,即属性为@Retention(RetentionPolicy.RUNTIME)的注解.

在java.lang.reflect中的AnnotatedElement接口是所有程序元素的(Class,Method)父接口,我们可以通过反射获取到某个类的AnnotatedElement对象,进而可以通过该对象提供的方法访问Annotation信息,常用的方法如下:

如何理解Java注解和注解解析器

运行时注解处理器的编写本质上就是通过反射获取注解信息,随后进行其他操作。编译一个运行时注解处理器就是这么简单。运行时注解通常多用于参数配置类模块。

编译时注解处理器

不同于运行时注解处理器,编写编译时注解处理器(Annotation Processor Tool).

APT用于在编译时期扫描和处理注解信息.一个特定的注解处理器可以以java源码文件或编译后的class文件作为输入,然后输出另一些文件,可以是.java文件,也可以是.class文件,但通常我们输出的是.java文件.(注意:并不是对源文件修改).如果输出的是.java文件,这些.java文件回合其他源码文件一起被javac编译.

你可能很纳闷,注解处理器是到底是在什么阶段介入的呢?好吧,其实是在javac开始编译之前,这也就是通常我们为什么愿意输出.java文件的原因.

注解最早是在java 5引入,主要包含apt和com.sum.mirror包中相关mirror api,此时apt和javac是各自独立的。从java 6开始,注解处理器正式标准化,apt工具也被直接集成在javac当中。

我们还是回到如何编写编译时注解处理器这个话题上,编译一个编译时注解处理主要分两步:

1、继承AbstractProcessor,实现自己的注解处理器

2、注册处理器,并打成jar

首先来看一下一个标准的注解处理器的格式:

  1. public class MyAnnotationProcessor extends AbstractProcessor { 

  2.  

  3.  

  4.     @Override 

  5.     public Set<String> getSupportedAnnotationTypes() { 

  6.         return super.getSupportedAnnotationTypes(); 

  7.     } 

  8.  

  9.  

  10.     @Override 

  11.     public SourceVersion getSupportedSourceVersion() { 

  12.         return super.getSupportedSourceVersion(); 

  13.     } 

  14.  

  15.  

  16.     @Override 

  17.     public synchronized void init(ProcessingEnvironment processingEnv) { 

  18.         super.init(processingEnv); 

  19.     } 

  20.  

  21.  

  22.     @Override 

  23.     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 

  24.         return false; 

  25.     } 


如何理解Java注解和注解解析器

编写一个注解处理器首先要对ProcessingEnvironment和RoundEnvironment非常熟悉。接下来我们一览这两个类的风采.首先来看一下ProcessingEnvironment类:

public interface ProcessingEnvironment {       Map<String,String> getOptions();       //Messager用来报告错误,警告和其他提示信息     Messager getMessager();       //Filter用来创建新的源文件,class文件以及辅助文件     Filer getFiler();       //Elements中包含用于操作Element的工具方法     Elements getElementUtils();        //Types中包含用于操作TypeMirror的工具方法     Types getTypeUtils();       SourceVersion getSourceVersion();       Locale getLocale(); }

Element

element表示一个静态的,语言级别的构件。而任何一个结构化文档都可以看作是由不同的element组成的结构体,比如XML,JSON等。

对于java源文件来说, Element代表程序元素:包,类,方法都是一种程序元素 ,他同样是一种结构化文档:

package com.closedevice;             //PackageElement public class Main{                  //TypeElement     private int x;                  //VariableElement     private Main(){                 //ExecuteableElement     }     private void print(String msg){ //其中的参数部分String msg为TypeElement     } }

如何理解Java注解和注解解析器

TypeMirror

这三个类也需要我们重点掌握:

DeclaredType代表声明类型:类类型还是接口类型,当然也包括参数化类型,比如Set<String>,也包括原始类型

TypeElement代表类或接口元素,而DeclaredType代表类类型或接口类型。

TypeMirror代表java语言中的类型.Types包括基本类型,声明类型(类类型和接口类型),数组,类型变量和空类型。也代表通配类型参数,可执行文件的签名和返回类型等。TypeMirror类中最重要的是getKind()方法,该方法返回TypeKind类型,为了方便大家理解,这里附上其源码:

public enum TypeKind {     BOOLEAN,BYTE,SHORT,INT,LONG,CHAR,FLOAT,DOUBLE,VOID,NONE,NULL,ARRAY,DECLARED,ERROR,  TYPEVAR,WILDCARD,PACKAGE,EXECUTABLE,OTHER,UNION,INTERSECTION;     public boolean isPrimitive() {         switch(this) {         case BOOLEAN:         case BYTE:         case SHORT:         case INT:         case LONG:         case CHAR:         case FLOAT:         case DOUBLE:             return true;         default:             return false;         }     } }

简单来说,Element代表源代码,TypeElement代表的是源码中的类型元素,比如类。虽然我们可以从TypeElement中获取类名,TypeElement中不包含类本身的信息,比如它的父类,要想获取这信息需要借助TypeMirror,可以通过Element中的asType()获取元素对应的TypeMirror。

然后来看一下RoundEnvironment,这个类比较简单,一笔带过:

public interface RoundEnvironment {     boolean processinGover();      //上一轮注解处理器是否产生错误     boolean errorRaised();      //返回上一轮注解处理器生成的根元素     Set<? extends Element> getRootElements();    //返回包含指定注解类型的元素的集合     Set<? extends Element> getElementsAnnotatedWith(TypeElement a);     //返回包含指定注解类型的元素的集合     Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a); }

Filer

Filer用于注解处理器中创建新文件,由于Filer用起来实在比较麻烦,后面我们会使用javapoet简化我们的操作.

打包注解处理器的时候需要一个特殊的文件 javax.annotation.processing.Processor 在 META-INF/services 路径下

如何理解Java注解和注解解析器

新建项目必要配置:

//javapoet代码生成框架 implementation  'com.squareup:javapoet:1.8.0'  //注解处理器 implementation 'com.google.auto.service:auto-service:1.0-rc6' annotationProcessor  'com.google.auto.service:auto-service:1.0-rc6'

编译时注解demo示例地址:https://gitee.com/yutg/apt.git

项目结构

--apt-demo ----bindview-annotation(Java Library)//注解定义 ----bindview-api(Android Library)//定义SDK接口方法 ----bindview-compiler(Java Library)//注解处理器相关操作及生成java文件 ----app(Android App)

感谢各位的阅读,以上就是“如何理解Java注解和注解解析器”的内容了,经过本文的学习后,相信大家对如何理解Java注解和注解解析器这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 如何理解Java注解和注解解析器

本文链接: https://www.lsjlt.com/news/83221.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何理解Java注解和注解解析器
    这篇文章主要讲解了“如何理解Java注解和注解解析器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Java注解和注解解析器”吧!什么是元数据(met...
    99+
    2022-10-19
  • 如何理解Java注解
    本篇内容介绍了“如何理解Java注解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!由@Autowired引...
    99+
    2022-10-19
  • java注解与元注解实例分析
    这篇文章主要介绍“java注解与元注解实例分析”,在日常操作中,相信很多人在java注解与元注解实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java注解与元注解实例分析”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-30
  • 如何理解Java注解编程
    本篇内容主要讲解“如何理解Java注解编程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解Java注解编程”吧!注解是什么实现格式从代码来看我们知道注解的实现格式是:public ...
    99+
    2023-06-15
  • Spring注解@Import原理解析
    目录正文@Import 原理示例 @EnableAsync正文 在项目开发的过程中,我们会遇到很多名字为 @Enablexxx 的注解,比如@EnableApolloConfig、...
    99+
    2023-02-24
    Spring注解@Import Spring @Import Spring注解
  • spring注解@Service注解的使用解析
    @Service注解的使用 要说明@Service注解的使用,就得说一下我们经常在spring配置文件applicationContext.xml中看到如下图中的配置: <...
    99+
    2022-11-12
  • Java|注解之定义注解
    Java语言使用@interface语法来定义注解(Annotation),它的格式如下: public @interface Report { int type() default 211; String level() de...
    99+
    2023-09-14
    java
  • Java注解处理器的示例分析
    这篇文章将为大家详细讲解有关Java注解处理器的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就...
    99+
    2023-05-30
  • Java注解详解
    目录 一、发现注解二、注解是什么1. 注解的本质2. 注解是针对Java编译器的说明 三、为什么要使用注解四、Java中常用的注解4.1 基础注解(spring-context、spring-we...
    99+
    2023-08-22
    java spring 软件测试
  • Spring注解@DependsOn解析
    目录介绍注解详情使用源码解析总结介绍 今天要分享得是Spring的@DependsOn注解,对于@DependsOn,我们从它的名称里面就能看出意思是“依赖于&rdquo...
    99+
    2023-05-17
    Spring注解@DependsOn Spring注解 Spring @DependsOn
  • 深入理解Java:注解(Annotation)自定义注解入门
     要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法。元注解:  元注解的作用就是负责注解其他注解。Java5.0定...
    99+
    2022-10-18
  • Java@GlobalLock注解详细分析讲解
    目录GlobalLock的作用全局锁为什么要使用GlobalLock工作原理GlobalLock的作用 对于某条数据进行更新操作,如果全局事务正在进行,当某个本地事务需要更新该数据时...
    99+
    2022-11-21
    Java @GlobalLock Java @GlobalLock注解
  • Java注解
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、在编译时进行格式检查(JDK内置的三个基本注解)二、使用步骤1.理解Annotation2.Annocat...
    99+
    2023-10-10
    java 开发语言
  • 【Java 注解】自定义注解(注解属性与使用)
    文章目录 前言一、自定义注解与元注解1.注解属性类型 二、注解的生命周期以及作用目标1.生命周期2.作用目标 三,简单使用四,注解属性赋值简化 前言 Java注解是一种元数据(m...
    99+
    2023-10-21
    java spring spring boot log4j 经验分享 笔记 后端
  • Java注解Annotaton详解
    目录1、三种基本的Annotaton@Override解读细节@Deprecated解读效果细节可以修饰方法,类,包,参数等等@SuppressWarnings解读效果细节元注解Re...
    99+
    2022-11-13
  • Lombok的@StandardException注解解析
    目录1. 引言2. 什么是 @StandardException2.1. 添加 Lombok 依赖2.2. 使用类注解3. 优点4. 缺点5. 结论1. 引言 在 Java 应用程序...
    99+
    2023-05-19
    Lombok @StandardException注解 Lombok 注解
  • CDS view注解解析 - @Environment.systemField
    下面的CDS view使用到了@Environment.systemField这个注解,定义了两个参数#SYSTEM_LANGUAGE和#USER。 这个view从CRM物料主数据的产品抬头表CO...
    99+
    2022-10-18
  • Spring注解解析之@ImportResource
    目录一、ImportResource1.1 定义包和类1.2 定义配置文件1.3 定义Java Config类1.4 测试代码二、运行一、ImportResource 1.1 定义包...
    99+
    2022-11-12
  • Java中注解、元注解怎么用
    这篇“Java中注解、元注解怎么用”除了程序员外大部分人都不太理解,今天小编为了让大家更加理解“Java中注解、元注解怎么用”,给大家总结了以下内容,具有一定借鉴价值,内容详细步骤清晰,细节处理妥当,希望大家通过这篇文章有所收获,下面让我们...
    99+
    2023-06-29
  • SpringMVC注解之@ResponseBody注解原理
    目录一、介绍二、作用范围三、源码分析四、总结一、介绍 @ResponseBody 注解的作用是将方法的返回值通过适当的转换器转换为指定的格式之后,写入到 response ...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作