代码改变世界

注解

2019-04-23 17:30  般若Android  阅读(313)  评论(0编辑  收藏  举报

 

Android自定义注解(Annotation)

  现在市面上很多框架都有使用到注解,比如butterknife、EventBus库、Retrofit库等等。

  注解(Annotation)是JDK1.5新增加的功能,注解其实就是添加类、变量、方法、参数等前面的一个修饰符一个标记,比如下面代码里面@Override、@IdRes就是注解

  @Override public <T extends View> T findViewById(@IdRes int id) {

     return getDelegate().findViewById(id);

     }

  上面强调了注解就是一个修饰符一个标记,但是通过注解能做的事情确是无穷,在代码编译或者运行的过程中我们可以找到这些注解,在找到这些注解之后咱们可以做很多事情,比如自动做一些代码处理(赋值、检测、调用等等)或者干脆生成一些额外的java文件等。

  注解的作用:简化代码,提高开发效率

  元注解

  元注解是用来定义其他注解的注解(自定义注解的时候需要使用元注解来定义我们的注解)。java.lang.annotation提供了四种元注解:@Retention @Inherited     @Documented @Target

  

  元注解 说明
  @Target 表明我们注解可以出现的地方。是一个ElementType枚举
  @Retention 这个注解的的存活时间
  @Document 表明注解可以被javadoc此类的工具文档化
  @Inherited 是否允许子类继承该注解,默认为false
  @Target

  @Target元注解用来表明我们注解可以出现的地方,参数是一个ElementType类型的数组,所以@Target可以设置注解同时出现在多个地方,即可以出现在类的前面,也可以出现在变量的前面

  

  @Retention

  @Retention表示需要什么级别保存该注释信息,用于描述注解的生命周期(被描述的注解在什么范围内有效)参数是RetentionPolicy枚举对象

  

  @Document

  @Document表明我们标记的注解可以被javadoc此类的工具文档化

  @Inherited

  @Inherited表明我们标记的的注解是被继承的。比如一个父类使用了@Inherited修饰的注解,则允许子类继承该父类的注解

  自定义注解

  自定义运行时注解

  运行时注解:在代码运行的过程中通过反射机制找到我们自定义的注解,然后做相应的事情

  自定义运行注解大的方面分为两步:一个是申明注解,一个是解析注解

  申明注解

  申明注解步骤

  1.通过@Retention(RetentionPolicy.RUNTIME)元注解确定我们的注解是在运行的时候使用

  2.通过@Targe确定我们注解是作用在什么上面的(变量、函数、类)

  3.确定注解我们需要的参数

  比如下面我们申明一个作用在变量上的BindString运行时注解

  @Retention(RetentionPolicy.RUNTIME)

   @Target(ElementType.FIELD)

  public @interface BindString {

    int value();

   }

  注解解析

  运行时注解解析时简单的分为三个步骤

  1.找到对应的所有属性或者方法

  2.找到添加了我们注解的属性或者方法

  3.做我们注解需要自定义的一些操作。

  找到添加注解的属性或者方法

  每个属性对应Field 每个方法对应Method而且Field和Method都实现了AnnotatedElement接口。都有AnnotatedElement接口,我们就可以很容易的找到添加了我们指定注解的方法或者属性

  

 

 自定义注解需要做的事情

  添加了我们注解的属性或者方法已经拿到了,之后要做的就是自定义注解自定义的一些事情了,比如在某些特定条件下自动去执行我们添加注解的方法

  通过注解自动创建对象

  代码过程中我们经常定义了一个对象,但是经常忘了创建对象,抛出空指针异常,接下来我们定义一个AutoWired注解来自动去帮我们创建对象

  AutoWired注解的声,指定注解是在变量上使用,并且在运行时有效。

AutoWired注解的解析,找到AutoWired注解的变量,创建对象,在吧对象赋值给AutoWired指定的那个变量

 

 

 

 注意:运行时注解需要在程序中调用 故多用于初始化参数等方面

  自定义编译时注解

  编译时注解就是在编译的过程中用一个javac注解处理器来扫描到我们自定义的注解,生成我们需要的一些文件(通常是java文件)

  自定义编译注解的步骤

  1.声明注解

  2.编写注解处理器

  3.生成文件(通常是JAVA文件)

  第二步和第三步是柔和的

  下面的例子我们自定义一个作用在类上的编译时注解Factory,并且这个注解是需要两个参数的,一个Class类型,一个是String类型

  

  编写注解处理器

  和运行时注解的解析不一样,编译时注解的解析需要去实现一个注解处理器

   注解处理器(Annotation Procesor)是java 的一个工具,它用来编译时扫描和处理注解,一个注解的注解处理器,以java代码(或者编译过的字节码)作为输出,生成文件(通常是java文件)作为输出,而且这些生成的java文件同手动编写的java源代码一样可以调用(不能修改已经存在的java文件代码)

  注解处理器所做的工作,就是在代码编译的过程中,找到我们指定的注解,然后让我们增加自己特定的逻辑做出相应的处理(通常是生成java文件)

  注解处理器的写法有固定的套路

  1.注册注解处理器()

  2.自定义注解处理器类继承AbstractProcessor

  注册注解处理器

  打包注解处理器的时候需要一个特殊的文件javax.annotation.processing.Processor在META-INF/services路径下。在javax.annotation.processing.Processor文件里面写上我们自定义注解处理器的全称(包加类的名字)如果有多个注解处理器换行写入就可以

  注解处理器的库@AutoService(Processor.class)的注解来简化我们操作,我们只需要在我们自定义的注解处理器类前面加上这个注解,在打包的时候就会自动生成javax.annotation.processing.Processor文件,写入信息,不需要手动去创建,需要加入依赖compile 'com.google.auto.service:auto-service:1.0-rc3'

自定义注解处理器类

  自定义注解处理器类一定要继承AbstractProcessor,否则找不到我们需要的注解,在这个类里面找到我们需要的注解,做出相应的处理

  关于AbstractProcessor里面的一些函数简单的介绍

  

   编译时注解实例

  通过自定义注解实现工厂模式,每个工厂模式通常都有一个相应的Factory的帮助类来选择具体的工厂类,我们现在就想通过编译时注解生成这个Factory帮助类,不用手动编写