前言
之前对 arouter-api 做了整个流程的分析,今天来看看 arouter-compiler 。
arouter-compiler 主要是利用 apt 在编译期自动生成代码的。之前我们看到的 ARouter$$Root$$app
、 ARouter$$Group$$test
和 Test1Activity$$ARouter$$Autowired
等都是 arouter-compiler 生成的。
那接下来就分析分析 arouter-compiler 是怎么生成这些源码的。
arouter-compiler
arouter-compiler 中 processor 有三种:
- AutowiredProcessor : 用来生成像
Test1Activity$$ARouter$$Autowired
这种类型; - InterceptorProcessor : 用来生成像
ARouter$$Interceptors$$app
这种类型; - RouteProcessor : 用来生成像
ARouter$$Root$$app
,ARouter$$Providers$$app
和ARouter$$Group$$test
这种类型;
RouteProcessor
在这里我们就只分析 RouteProcessor 了。
RouteProcessor 相比其他两个 Processor 来说,代码更长,逻辑更加复杂。并且 RouteProcessor 主要处理的是路由映射这一块。其他两个 RouteProcessor 也是大同小异,有兴趣的同学可以自行阅读源码。
先来看看 RouteProcessor 的定义:
@AutoService(Processor.class)
@SupportedOptions({KEY_MODULE_NAME, KEY_GENERATE_DOC_NAME})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes({ANNOTATION_TYPE_ROUTE, ANNOTATION_TYPE_AUTOWIRED})
public class RouteProcessor extends AbstractProcessor {
...
}
RouteProcessor 类上面的注解很多,我们一个一个来看:
- @AutoService 会自动在 META-INF 文件夹下生成 Processor 配置信息文件,避免手动配置的麻烦;
- @SupportedOptions 指定 Processor 支持的选项参数名称,KEY_MODULE_NAME 就是 AROUTER_MODULE_NAME ,KEY_GENERATE_DOC_NAME 就是 AROUTER_GENERATE_DOC;没错,这两个就是我们一开始在 build.gradle 中配置的。
- @SupportedSourceVersion 指定 Processor 支持的 JDK 的版本;
- @SupportedAnnotationTypes 指定 Processor 处理的注解;
接着,趁热打铁。来瞧瞧 RouteProcessor 的 init 方法。
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
mFiler = processingEnv.getFiler(); // Generate class.
types = processingEnv.getTypeUtils(); // Get type utils.
elements = processingEnv.getElementUtils(); // Get class meta.
typeUtils = new TypeUtils(types, elements);
logger = new Logger(processingEnv.getMessager()); // Package the log utils.
// Attempt to get user configuration [moduleName]
Map<String, String> options = processingEnv.getOptions();
if (MapUtils.isNotEmpty(options)) {
moduleName = options.get(KEY_MODULE_NAME);
generateDoc = VALUE_ENABLE.equals(options.get(KEY_GENERATE_DOC_NAME));
}
if (StringUtils.isNotEmpty(moduleName)) {
moduleName = moduleName.replaceAll("[^0-9a-zA-Z_]+", "");
logger.info("The user has configuration the module name, it was [" + moduleName + "]");
} else {
logger.error(NO_MODULE_NAME_TIPS);
throw new RuntimeException("ARouter::Compiler >>> No module name, for more information, look at gradle log.");
}
// 如果需要生成路由 doc
if (generateDoc) {
try {
docWriter = mFiler.createResource(
StandardLocation.SOURCE_OUTPUT,
PACKAGE_OF_GENERATE_DOCS,
"arouter-map-of-" + moduleName + ".json"
).openWriter();
} catch (IOException e) {
logger.error("Create doc writer failed, because " + e.getMessage());
}
}
iProvider = elements.getTypeElement(Consts.IPROVIDER).asType();
logger.info(">>> RouteProcessor init. <<<");
}
在 init 方法中,主要获取了 KEY_MODULE_NAME 和 KEY_GENERATE_DOC_NAME 这两个编译选项参数。然后判断一下是否需要生成路由文档。
在 init 方法中获取参数后,接着就是 process 方法。
process 方法就好像是 main 方法一样,在这里面都是 processer 处理注解自动生成代