天天看点

JAVA 注解 processor_Annotation Processor(注解处理器)详解

前言

注解处理器

自定义处理器

前言

Java中的注解(Annotation)如果要被识别,离不开注解处理器。所以有必要来了解一下。

注解处理器

注解处理器(Annotation Processor)是javac的一个工具,不管是运行时注解还是编译时注解,都会通过处理器在编译时进行扫描和处理注解。

Java中有默认的注解处理器,使用者也可以自定义注解处理器,注册后使用注解处理器处理注解,最终达到注解本身起到的效果。

注解处理器将标记了注解的类,变量等作为输入内容,经过注解处理器处理,生成想要生成的java代码。所以处理器可以理解为就是一个生成代码的工具,只是是通过注解的规则生成。生成后的代码,可以看作是同一般代码,最终被编译。

自定义处理器

创建工程

自定义处理器需要创建java 库java- Library(自行创建)

添加依赖

implementation 'com.google.auto.service:auto-service:1.0-rc3'

implementation 'com.google.auto:auto-common:0.8'

创建自定义Processor类 如创建MyProcessor

MyProcessor继承 AbstractProcessor 添加@AutoService(Processor.class)注解

如:

@AutoService(Processor.class)

public class PermissionProcessor extends AbstractProcessor {

@Override

public synchronized void init(ProcessingEnvironment processingEnvironment) {

super.init(processingEnvironment);

}

@Override

public Set getSupportedAnnotationTypes() {

return super.getSupportedAnnotationTypes();

}

@Override

public SourceVersion getSupportedSourceVersion() {

return super.getSupportedSourceVersion();

}

@Override

public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {

return false;

}

init(ProcessingEnvironment processingEnvironment)

init()方法,它会被注解处理工具调用,并输入ProcessingEnviroment参数。

ProcessingEnviroment提供很多有用的工具类Elements, Types和Filer。

getSupportedAnnotationTypes()

这里你必须指定,这个注解处理器是注册给哪个注解的。

注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。换句话说,你在这里定义你的注解处理器注册到哪些注解上。

getSupportedSourceVersion()

用来指定你使用的Java版本。通常这里返回SourceVersion.latestSupported()。

如果你有足够的理由只支持Java 6的话,你也可以返回SourceVersion.RELEASE_6

建议使用前者

process(Set extends TypeElement> set, RoundEnvironment roundEnvironment)

这相当于每个处理器的主函数main()。扫描、评估和处理注解的代码,以及生成Java文件。

输入参数RoundEnviroment,可以让你查询出包含特定注解的被注解元素。后面我们将看到详细的内容。

注:在Java 7中,你也可以使用注解来代替getSupportedAnnotationTypes()和getSupportedSourceVersion(),像这样:

@SupportedAnnotationTypes(“com.starcor.annotation.RouterAnnotation”),其中括号内内容表示要处理的注解名称,要写全名。

创建javax.annotation.processing.Processor 注册注解处理器

在使用注解处理器需要先声明,步骤:

1、需要在 processors 库的 main 目录下新建 resources 资源文件夹;

2、在 resources文件夹下建立 META-INF/services 目录文件夹

3、创建javax.annotation.processing.Processor文件

4、文件内容添加:com.xx.java.processor.MyProcessor 自己创建注解处理器的路径

ProcessingEnvironment 包含了注解处理器相关的工具类和编译器配置的参数

public interface ProcessingEnvironment {

Map getOptions(); // 编译期间,app给注解处理器传的值

Messager getMessager(); // 在注解处理器处理注解生成新的源代码过程中,我们可用Messager来将一些错误信息打印到控制台上

Filer getFiler(); // 我们可以通过这个类来创建新的文件。

Elements getElementUtils();

Types getTypeUtils();

SourceVersion getSourceVersion();

Locale getLocale();

}

RoundEnvironment 指在每一轮的扫描和处理源代码中获取被注解的Element

获取被注解的Element

Set extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(GetPermissions.class);

遍历Element 获取相应添加注解的信息

mElementUtils.getPackageOf(element); // 获取包名, 通过工具类

TypeElement classElement = (TypeElement) element.getEnclosingElement(); // 获取类

classElement.getSimpleName().toString(); // 获取类名

element.getAnnotation(注解类.class); // 获取注解的实体类对象,可获取里面相应的值

element.getModifiers() // 获取修饰符

// 强转方法的Element

ExecutableElement methodElement = (ExecutableElement) element;

// 获取方法名

String methodName = methodElement.getSimpleName().toString();

executableElement.getParameters(); // 获取注解形参

executableElement.getReturnType(); // 获取返回值类型

enclosingElement.getTypeParameters(); // 获取返回值

executableElement.getThrownTypes(); // 获取方法throw的异常