注解
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帮助类,不用手动编写