Booster 架构概述
Booster 的架构设计
可扩展性是 Booster 架构的核心需求,通过功能模块化,让功能开发相对更独立,也方便功能的测试和灰度验证,除此之外,还要解决这些问题:
- 如何让模块的开发变得更容易?
- 当功能模块足够多时,如何保证构建的性能?
- 如何解决开源协议冲突的问题?
为了能很好的解决这些问题,最终 Booster 的架构被设计成如下图所示:
如何实现可扩展?
为了实现功能模块的动态发现与加载,Booster 以 SPI (Service Provider Interface) 为基础,通过 Google AutoService 简化了 SPI 的配置,在 Booster 中提供了两大类 SPI:
- Task SPI 用于在 Gradle 的 Task Graph 中插入自定义的 task,例如:booster-task-compression-cwebp在新窗口打开, booster-task-compression-pngquant在新窗口打开 等等。 
- Transformer SPI 用于在 Transform 的过程中插入自定义的 Transformer 对字节码进行操作。为了照顾到大多数的开发者,Booster 中提供了两种 Transformer SPI: - 基于 ASM 的 ClassTransformer在新窗口打开
- 基于 Javassist 的 ClassTransformer在新窗口打开
 - 开发者可以根据自己的喜好,选择使用 ASM 或者 Javassist。 
如何让开发变得更容易?
在开发体验和便利性上,Booster 主要做了这些事情:
- 抽象 Transform 过程,直接将解析好的 class 文件结构暴露给开发者;
- 将 Transform 与 Gradle 解耦,在非 Gradle 工程中同样可以复用 Booster 的 Transformer;
- 通过 VariantProcessor在新窗口打开 解决注入外部库的依赖问题,使得大规模字节码注入成为可能;
- 从 AGP 3.0 开始,依次对 AGP 的每个版本进行兼容性适配,并抽象出通用的 Android Gradle API在新窗口打开,使得开发者不用关心 AGP 各版本间的差异;
- 提供了一系列实用的工具类库,为功能模块开发提升效率;
如何保证构建的性能?
- 支持增量构建 - 无论是 Transform 还是其它的 Task,都支持增量构建。 
- 一次文件系统 I/O - 从 Booster 的源码中可以看到,整个 Transform 过程只涉及到一次读写文件系统,所有的 Transformer 都是访问内存中的 Class 结构 
- Transformer Pipeline 与并行 Transformer - 整个 Transform 的过程以单个 JAR 或目录为粒度进行流式处理,各个 Transformer Pipeline 并行执行,最大限度利用 CPU 资源。 
- 并行写磁盘 - 通过并行方式将 class 写回 JAR 中。 
- 性能测试 - 通过 JMH 对多个技术方案进行 benchmark 测试,选择性能最优的方案,详见:booster-benchmark在新窗口打开。 
如何解决开源协议冲突?
在 Booster 中,除了 Task SPI在新窗口打开 和 Transform SPI在新窗口打开 以外,还提供了一种 SPI —— Command SPI在新窗口打开。
Command SPI在新窗口打开 主要是为了解决在 Apache License 的协议许可下使用 GPL License 的开源软件,如:pngquant 采用了 GPL License 开源许可,直接在项目中使用会有一定的法律风险,所以 Booster 的做法是将部分抽象出来,以 SPI 的形式在运行时动态发现和加载 Command SPI 的实现,这样,既能保证开源许可的合法性,又能使用优秀的 GPL 开源软件。
