Annotation Processor: 自定义注解处理器,不再写烦人的模板代码

本文介绍了Java中的注解处理器,它在编译时期工作,无需反射,常用于生成样板代码。文章详细阐述了注解处理器的工作原理、注册方式以及如何创建一个注解处理器。通过实例展示了创建注解和处理器的过程,同时探讨了ButterKnife的内部机制,揭示了注解处理器如何简化代码并提高效率。
摘要由CSDN通过智能技术生成

注解处理在 Java 1.5 的时候就已经发布了,虽然它很老了,但是却是最强大的 API 之一。下面我们会先讨论注解处理,代码自动生成以及使用到这些技术的开源库。

什么是注解

实际上,我们应该都知道什么是注解。我们经常使用到的:@Override@Singleton@StringRes 等等,这些就是注解。

注解是一种可以添加到Java源代码的语法元数据。 我们可以注释类,接口,方法,变量,参数等。 可以从源文件中读取Java注解。 Java注解也可以嵌入和读取编译器生成的类文件。 Java VM可以在运行时保留注解,并通过反射进行读取

比如:

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface BindView {
   
    int value();
}

创建一个注解需要两部分信息: RetentionTarget

RetentionPolicy 指定了注解应该保留到程序生命周期的什么时候。举个例子:注解可以保留到程序的编译时期或者运行时期。

ElementTypes 指定了注解应该作用于程序的哪一个部分。有3个取值:

  • SOURCE —— 编译时期,不会储存
  • CLASS —— 储存在 class 文件中,但是不会保留到运行时期
  • RUNTIME —— 储存在 class 文件中,运行时期可以访问(通过反射)

BindView 注解来说,RetentionPolicy.SOURCE 表示注解只需要在编译时期保存,之后就不需要了。ElementType.FIELD 表示该注解只能修饰字段。

注解处理器介绍

编译时期

Annotation Processor 实际上是 javac 编译器的一部分,所以注解处理时发生在编译时期,这有许多好处,其中之一就是“在编译其实发生错误比运行时期发生错误要好的多”。

无反射

Java 的反射 API 会在运行时抛出许多错误,这实在是有点蛋疼。但是 Annotation Processor 就不一样了,它会直接给我们一个程序的语义结构,我们使用这个语义结构就可以分析注解所处的上下文场景,然后做处理。

生成样板代码

Annotation Processor 最大的用处就是用来生成样板代码了,比如著名的 ButterKnife 等开源库。

注意:注解处理器只能生成新的文件,无法更改已经存在的文件

注解处理器是如何工作的

注解处理会执行很多轮。编译器首先会读取java源文件,然后查看文件中是否有使用注解,如果有使用,则调用其对应的注释处理器,这个注解处理器(可能会)生成新的带有注解的java源文件。这些新注解将再次调用其相应的注释处理器,然后再次生成更多的java源文件。就这样一直循环,直到没有新的文件生成。

在这里插入图片描述

注册注解处理器

java 编译器需要知道所有的注解处理器,所以如果我们想要自定义一个处理器,我们必须要让 java 编译器知道我们创建了一个。

有两种方法来注册一个处理器:

  • 老方法:

    创建一个目录:

    <your-annotation-processor-module>/src/main/resources/META-INF/services
    

    然后在services文件夹里面,创建一个名字叫做javax.annotation.processing.Processor的文件。在这个文件中声明你的处理器的权限定名:

    <your-package>.YourProcessor
    
  • 新方法:

    使用谷歌的 AutoService 库。

    package foo.bar;
    import javax.annotation.processing.Processor;
    @AutoService(Processor.class)
    final class MyProcessor implements Processor {
         
      // …
    }
    

    注意在 gradle 文件中引入依赖。

创建一个注解处理器

首先,我们需要继承一个父类:

public class Processor extends AbstractProcessor {
   
    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
   
        super.init(processingEnvironment);
        // initialize helper/utility classes...
    
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值