Skip to content

Latest commit

 

History

History
63 lines (38 loc) · 2.84 KB

注解处理器要点.md

File metadata and controls

63 lines (38 loc) · 2.84 KB

注解处理器的几个要点

  1. apt是javac提供的工具,他不能改变源文件,只能生成新的文件
  2. 自定义的注解处理器需要先注册(@AutoService(Processor.class))
  3. 在库中可以指明要使用的注解处理器库(annotationProcessor project(path: ':brouter_processor'))

注解处理器对apk体积的影响

一般我们会将注解处理器单独放在一个库中,因为他只是在编译阶段辅助生成java文件,生成的apk并不需要用到这个库,所以不会对apk的体积产生影响。

方法介绍

boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv);

一般来说,这个方法使用了做一些初始化工作的,但是它可以搞一些骚操作。

比如,我们通常生成 java 文件是在 javax.annotation.processing.Processor#process 中,但是有时候我们可能有这样的需求,那就是,当 module 里面没有对应的注解时,我们也想生成 java 文件,该怎么办呢?

我们看看 processor 的方法调用逻辑:

首先,它会执行 init 方法,然后会调用 javax.annotation.processing.AbstractProcessor#getSupportedAnnotationTypes (这些方法只会被调用一次)等方法,最后再调用 process 方法。

所以,就算 module 里面没有指定的注解,注解处理器的 init 方法也会被调用。javax.annotation.processing.AbstractProcessor#getSupportedAnnotationTypes 这个方法并不影响 init 方法。

最后的解决方法,就是将生成 java 类的逻辑,放入到 init 里面。

Set getSupportedAnnotationTypes();

这里你必须指定,这个注解处理器是注册给哪个注解的,换句话说,你在这里定义你的注解处理器注册到哪些注解上,返回空会导致注解处理器拿不到任何注解修饰的元素。注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。

一些奇怪的地方

我们知道,注解处理器里面可以有方法,但是返回值是有限制的,看这样的一个注解:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Conditional {
    Class<?> condition();
}

这个注解的 conditions 方法返回了一个 class 对象。这没什么大不了的,但是我们在注解处理器中,获取该值的时候,获取不到,这是为什么呢?

final Class<?> interceptor = anno.condition(); // 代码无法往下执行

最后,发现原来是这个方法报错了,然后更奇葩的是,只能在 catch 里面取获取这个值

        try {
            final Class<?> interceptor = anno.condition();
        } catch (MirroredTypesException e) {
            // 这里是全类名
            final String className = e.getTypeMirrors().get(0).toString();
        }