Android 自定义注解处理器详解


Annotation Processor是javac的一个工具,它用来在编译时扫描和处理注解。通过Annotation Processor可以获取到注解和被注解对象的相关信息,然后根据注解自动生成Java代码,省去了手动编写,提高了编码效率。
在这里插入图片描述

图:编译器原理


AbstractProcessor

参考:http://www.matools.com/api/java8

旨在用作最具体注释 processor 的便捷超类的抽象注释 processor。此类检查注释值,以计算其子类型所支持的选项、注释和源版本。

在 processor 被初始化之后,获取方法可以使用可用设施来发出有关值得注意的条件的警告。

只要遵守该方法的常规 Processor 协定,子类可随意重写此类中任何方法的实现和规范。

在这里插入图片描述

方法详细信息

  • init:用处理环境初始化 processor,方法是将 processingEnv 字段设置为 processingEnv 参数的值。如果在同一对象上多次调用此方法,则抛出 IllegalStateException。参数:processingEnv - 用来访问工具框架提供给 processor 的设施的环境

  • getSupportedOptions:如果 processor 类是使用 SupportedOptions 注释的,则返回一个不可修改的集合,该集合具有与注释相同的字符串集。如果类不是以这种方式注释的,则返回一个空集合。

  • getSupportedAnnotationTypes:返回支持注释类型名称的set集合

  • getSupportedSourceVersion:返回注释中的源版本。

  • process:处理先前 round 产生的类型元素上的注释类型集,并返回这些注释是否由此 Processor 声明。如果返回 true,则这些注释已声明并且不要求后续 Processor 处理它们;如果返回 false,则这些注释未声明并且可能要求后续 Processor 处理它们。Processor 可能总是返回相同的 boolean 值,或者可能基于所选择的标准而返回不同的结果。
    如果 Processor 支持 “*” 并且根元素没有注释,则输入集合将为空。Processor 必须妥善处理空注释集。
    参数:annotations - 请求处理的注释类型;roundEnv - 有关当前和以前 round 的信息的环境
    返回:注释集是否由此 Processor 声明

  • getCompletions:返回一个空的 completion 迭代。
    参数:
    element - 将被注释的元素
    annotation - 将应用于元素的注释(可能是一部分)
    member - 为其返回可能 completion 的注释成员
    userText - 将补充完整的源代码文本

  • isInitialized
    如果此对象已被 初始化,则返回 true,否则返回 false。

ProcessingEnvironment

参考:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

注释处理工具框架将提供一个具有实现此接口的对象的注释 processor,因此 processor 可以使用该框架提供的设施来编写新文件、报告错误消息并查找其他实用工具。

第三方可能希望提供能包装此接口设施对象的增值包装器,例如,允许多个 processor 协同写出单个源文件的 Filer 扩展。为了实现这一点,对于在其副作用可通过 API 相互可见的上下文中运行的 processor,工具基础设施必须提供相应的设施对象,这些对象是 .equals、作为 .equals 的 Filer 等等。此外,必须能够配置工具调用,使得从运行注释 processor 的角度来看,至少已选定的帮助 (helper) 类子集可视为由相同的类加载器加载。(因为设施对象管理共享状态,所以包装器类的实现必须知道以前是否包装过相同的基本设施对象。)

在这里插入图片描述

方法详细信息

  • getOptions():返回传递给注释处理工具的特定于 processor 的选项。选项是以从选项名称到选项值的映射形式返回的。对于不包含任何值的选项,映射中的对应值为 null。
    关于如何传入特定于 processor 的选项的详细信息,请参阅特定工具基础设施的文档。例如,命令行实现可以通过使用已知字符串作为特定于 processor 的选项的前缀来区分它们;其他工具实现可能遵守不同的约定或提供替换机制。除了特定于 processor 的选项外,给定实现还可以提供特定于实现的方式来查找传递给该工具的选项。
    返回:传递给工具的特定于 processor 的选项

  • getMessager()
    返回用来报告错误、警报和其他通知的 Messager。
    返回:Messager

  • getFiler()
    返回用来创建新源、类或辅助文件的 Filer。
    返回:Filer

  • getElementUtils()
    返回用来在元素上进行操作的某些实用工具方法的实现。
    返回:元素实用工具

  • getTypeUtils()
    返回用来在类型上进行操作的某些实用工具方法的实现。
    返回:类型实用工具

  • getSourceVersion()
    返回任何生成的 源和 类文件应该符合的源版本。
    返回:生成的源和类文件应该符合的源版本

  • getLocale()
    返回当前语言环境;如果没有有效的语言环境,则返回 null。该语言环境可用来提供本地化的 消息。
    返回:当前语言环境;如果没有有效的语言环境,则返回 null



刚接触Annotation Processor的同学可能会遇到找不到AbstractProcessor类的问题,大概率是因为直接在Android项目里边引用了AbstractProcessor,然而由于Android平台是基于OpenJDK的,而OpenJDK中不包含Annotation Processor的相关代码。因此,在使用Annotation Processor时,必须在新建Module时选择Java Library,处理注解相关的代码都需要在Java Library模块下完成。我们需要看一下整个项目的结构
在这里插入图片描述

1 新建 Java Library

1.1 新建

新建两个 Java Library,在新建Module时选择下图:
在这里插入图片描述

名称分别为router_annotation和router_compiler(注解处理器),如下图:
在这里插入图片描述

1.2 确定依赖关系

在router_compiler中添加router_annotation为依赖库,如下图:
在这里插入图片描述

查看router_compiler的build.gradle文件,如下图:
在这里插入图片描述

2 创建自定义注解

在router_annotation中添加注解:

2.1 添加注解:Route

//添加元注解
// @Target(ElementType.TYPE)   //接口、类、枚举、注解
// @Target(ElementType.FIELD) //字段、枚举的常量
// @Target(ElementType.METHOD) //方法
// @Target(ElementType.PARAMETER) //方法参数
// @Target(ElementType.CONSTRUCTOR)  //构造函数
// @Target(ElementType.LOCAL_VARIABLE)//局部变量
// @Target(ElementType.ANNOTATION_TYPE)//注解
// @Target(ElementType.PACKAGE) ///包 
@Target(ElementType.TYPE)
//注解的生命周期
//RetentionPolicy.SOURCE  源码阶段
//RetentionPolicy.CLASS   编译阶段
//RetentionPolicy.RUNTIME 运行阶段
@Retention(RetentionPolicy.CLASS)
public @interface Route {
    /**
     *路由的路径,标识一个路由节点
     */
    String path();//没有默认值

    /**
     * 将路由节点进行分组,可以实现按组动态加载
     */
    String group() default "";//有默认值
}

因为String path()没有设置默认值,所有在使用Route注解的时候必须设置path的值。


2.2 添加注解 :Extra

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
public @interface Extra {
    String name() default "";
}

2.3 使用注解

app中添加router_annotation依赖。

在MainActivity添加注解:

@Route(path="/main/mainactivity")//1
public class MainActivity extends AppCompatActivity {
    @Extra(name="path")
    private String path;
}

注释1:在Route中path没有默认值,所以必须设置path。


3 注解处理器

在router_compiler中:

3.1 新建RouteProcessor

在router_compiler中新建自定义注解处理器RouteProcessor:

public class RouteProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        return false;
    }
}

3.2 注册注解处理器

在这个类上添加了@AutoService注解,它的作用是用来生成META-INF/services/javax.annotation.processing.Processor文件的,也就是我们在使用注解处理器的时候需要手动添加META-INF/services/javax.annotation.processing.Processor,而有了@AutoService后它会自动帮我们生成。AutoService是Google开发的一个库,使用时需要在 factory-compiler中添加依赖。


在router_compiler的build.gradle中添加依赖,如下:

 annotationProcessor 'com.google.auto.service:auto-service:1.0-rc6'
 compileOnly 'com.google.auto.service:auto-service:1.0-rc6'

在RouteProcessor中注册注解处理器:

/**
 * 在这个类上添加了@AutoService注解,它的作用是用来生成
 * META-INF/services/javax.annotation.processing.Processor文件的,
 * 也就是我们在使用注解处理器的时候需要手动添加
 * META-INF/services/javax.annotation.processing.Processor,
 * 而有了@AutoService后它会自动帮我们生成。
 * AutoService是Google开发的一个库,使用时需要在
 * factory-compiler中添加依赖
 */
@AutoService(Processor.class)   //注册注解处理器
public class RouteProcessor extends AbstractProcessor {
}

Make Project后查看生产的文件,如下图:
在这里插入图片描述
打开查看如下:
在这里插入图片描述
自动生成了RouteProcessor的路径。


3.3 覆写方法

在RouteProcessor中覆写3个方法,如下:

@AutoService(Processor.class)   //注册注解处理器
public class RouteProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        return false;
    }
    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
    }
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.RELEASE_7;
    }
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return super.getSupportedAnnotationTypes();
    }
}

这里也可以通过注解的方式实现,如下:

@AutoService(Processor.class)   //注册注解处理器

@SupportedOptions("moduleName")

@SupportedSourceVersion(SourceVersion.RELEASE_7)

@SupportedAnnotationTypes({"com.hongx.router_annotation.Route"})

public class RouteProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        return false;
    }
}

4 Android注解处理器(APT)简单实例

Android注解处理器(APT)简单实例

5 javapoet简单使用

在上面使用了StringBuilder来构建类的,比较麻烦,我们可以使用javapoet简化构建类过程。

javapoet

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值