Android使用注解处理器自动生成代码(了解)

作者: wenou | 来源:发表于2018-05-11 18:05 被阅读399次

    注解处理器(Annotation Processorjavac的一个工具,它是在编译时扫描注解和处理注解(Annotation)

    可以自定义注解,并注册相应的注解处理器

    在Andorid开源库中,有不少是使用到注解处理器的框架,像 Butterknife,Dagger2和路由ARouter等等

    依赖添加

    随着 Android Gradle 插件 2.2 版本的发布, android-apt 作者声明后续将不会继续维护android-apt,推荐使用 Android 官方插件提供的Android Gradle 插件的 annotationProcessor 功能来完全代替它

    Android Gradle 插件 2.2 版本前:

    //整个项目的build.gradle
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:1.5.0'
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        }
    }
    
    //APP的build.gradle中
    apply plugin: 'com.android.application'
    apply plugin: 'com.neenbedankt.android-apt'
    ...
    dependencies {
        ...
        apt 'xx.xxx: xxx:1.0.0'  //使用apt依赖项目
    }
    

    Android Gradle 插件 2.2 版本之后: 使用annotationProcessor 添加依赖项目

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])'
        ...
        annotationProcessor project(':router-compiler')
    }
    
    创建相应的模块

    名字随便起

    对应的模块

    1.创建一个annotation的java模块,创建需要用到的注解
    比如:这里创建了两个注解:

    注解
    @Target({ElementType.TYPE}) //注解使用范围,在class类上面使用
    @Retention(RetentionPolicy.CLASS) //注解生命周期
    public @interface Route {
        
    }
    

    2.创建一个compiler的java模块,在这个模块自定义注解处理器
    这里自定义了一个对应上面Route注解的注解处理器RouteProcessor

    @AutoService(Processor.class)  //自动注册
    @SupportedOptions(Consts.ARGUMENTS_NAME) //处理器接受参数
    @SupportedSourceVersion(SourceVersion.RELEASE_7) //指定java版本
    @SupportedAnnotationTypes({Consts.ANN_TYPE_ROUTE}) //处理的注解
    public class RouteProcessor extends AbstractProcessor {
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
           
            //编译期扫码到注解会调用到这里,在这里处理自动生成代码 
            return false;
        }
    }
    

    @SupportedAnnotationTypes 注册给哪些注解使用的?等于AbstractProcessor#getSupportedAnnotationTypes() 方法

    @SupportedSourceVersion 指定使用的Java版本AbstractProcessor#getSupportedSourceVersion()方法

    @SupportedOptions 处理器接收的参数 替代 AbstractProcessor#getSupportedOptions()方法

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

    注解处理器是需要注册才会被识别使用的,所以需要在这个模块下添加google自动注册服务依赖, 如下:

    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.google.auto.service:auto-service:1.0-rc2' //自动注册注解处理器
        implementation 'com.squareup:javapoet:1.7.0' //javapoet代码生成框架
    
        implementation project(':router-annotation') //依赖注解模块
    }
    

    当编译期扫描到注解,就会调用RouteProcessorprocess方法里面,在这里面处理自动生成代码的逻辑,可以使用javaPoet框架来处理需要生成的代码格式.

    JavaPoet是square推出的开源java代码生成框架,提供Java Api生成.java源文件

    @AutoService(Processor.class)
    @SupportedOptions(Consts.ARGUMENTS_NAME)
    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    @SupportedAnnotationTypes({Consts.ANN_TYPE_ROUTE})
    public class RouteProcessor extends AbstractProcessor {
        private Filer filer;
        @Override
        public synchronized void init(ProcessingEnvironment processingEnvironment) {
            super.init(processingEnvironment);
            filer = processingEnv.getFiler();
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            MethodSpec main = MethodSpec.methodBuilder("main")
                    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                    .returns(void.class)
                    .addParameter(String[].class, "args")
                    .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
                    .build();
            // HelloWorld class
            TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
                    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                    .addMethod(main)
                    .build();
            try {
                // build com.example.HelloWorld.java
                JavaFile javaFile = JavaFile.builder("com.example", helloWorld)
                        .addFileComment(" This codes are generated automatically. Do not modify!")
                        .build();
                // write to file
                javaFile.writeTo(filer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return true;
        }
    

    生成的java文件会在使用该注解Route的模块下的build目录下面:

    生成.java内容如下:

    package com.example;
    
    import java.lang.String;
    import java.lang.System;
    
    public final class HelloWorld {
      public static void main(String[] args) {
        System.out.println("Hello, JavaPoet!");
      }
    }
    

    这是一个简单的例子

    apt注解处理器在项目的应用例子:
    做一个自己简单的Router路由

    更多使用的技巧可参考javapoet 的github:
    https://github.com/square/javapoet#s-for-strings

    相关文章

      网友评论

        本文标题:Android使用注解处理器自动生成代码(了解)

        本文链接:https://www.haomeiwen.com/subject/sqzfdftx.html