Annotation Processor(注解处理器)详解

2019-12-31  本文已影响0人  caoww

前言

注解处理器

注解处理器(Annotation Processor)是javac的一个工具,不管是运行时注解还是编译时注解,都会通过处理器在编译时进行扫描和处理注解。
Java中有默认的注解处理器,使用者也可以自定义注解处理器,注册后使用注解处理器处理注解,最终达到注解本身起到的效果。

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

自定义处理器

创建工程
添加依赖
创建自定义Processor类 如创建MyProcessor
@AutoService(Processor.class)
public class PermissionProcessor extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return super.getSupportedAnnotationTypes();
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return super.getSupportedSourceVersion();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        return false;
    }
init()方法,它会被注解处理工具调用,并输入ProcessingEnviroment参数。
ProcessingEnviroment提供很多有用的工具类Elements, Types和Filer。
这里你必须指定,这个注解处理器是注册给哪个注解的。
注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。换句话说,你在这里定义你的注解处理器注册到哪些注解上。
用来指定你使用的Java版本。通常这里返回SourceVersion.latestSupported()。
如果你有足够的理由只支持Java 6的话,你也可以返回SourceVersion.RELEASE_6
建议使用前者
这相当于每个处理器的主函数main()。扫描、评估和处理注解的代码,以及生成Java文件。
输入参数RoundEnviroment,可以让你查询出包含特定注解的被注解元素。后面我们将看到详细的内容。
创建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<String, String> getOptions(); // 编译期间,app给注解处理器传的值

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

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

    /**
    * 它其实是一个工具类,用来处理所有的Element 元素,
    * 而我们可以把生成代码的类中所有的元素都可以成为Element 元素,
    * 如包就是PackageElement, 
    * 类/接口为TypeElement, 
    * 变量为VariableElement, 
    * 方法为ExecutableElement
    */
    Elements getElementUtils();

    /**
    * 它其实也是一个工具类,只是用来处理TypeMirror. 也就是一个类的父类。
    * TypeMirror superClassType = currentClass.getSuperclass();
    */
    Types getTypeUtils(); 

    SourceVersion getSourceVersion();

    Locale getLocale();
}

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

Set<? extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(GetPermissions.class);
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的异常
上一篇 下一篇

猜你喜欢

热点阅读