前言

  • 前一篇,我们介绍了gradle插件的整体使用,和asm的一些基础知识
  • 其实按照博主自己的经验来看,ASM我也没有系统地进行过学习,因为里面涉及到的内容确是比较庞杂。而我们平时插桩过程中,使用到的知识点并不是特别的海量。
  • 有需要的时候,再去针对部分盲点进行学习就好了。
  • 因此,这一篇,我们来真的聊一聊字节码插桩的应用。

应用

  • 其实,ASM也好,javassist也好,这些AOP的方案,已经出现很久了。反而是一些“老技术”了。只是因为Android的活跃,导致这些技术又重新被广泛应用了起来。
  • 不得不感叹,其实技术也是一个轮回。
  • 在Android领域,字节码插桩不仅仅应用于像美团Robust的热更新之中。
  • 还同时在:自动化埋点、Mock平台等等方面有很深远的应用。其中,自动化埋点确实是很大程度上解决了很多程序员在开发上的痛点。
  • 今天准备和大家聊一聊的,是字节码插桩上的另一个应用场景:组件化。

组件化

  • 大家都知道,一个App,在业务模块不断增加后,整个app会变得十分冗杂。导致的问题就是:不断爆增的业务和功能,不断新增的代码,会导致编译速度越来越慢。
  • 同时,一般来说我们每一次接需求,并不会对全盘所有功能进行改动,甚至在很多大型项目里,很多人长时间打交道的可能来来回回都是一小部分的代码。
  • 因此组件化解决的,一个是编译速度的问题,一个是开发效率的问题。把工程项目的每一个模块划分的非常精准,整个工程从下到上的体系分割清楚。

模块增多

  • 组件化的结果就是会拆分出很多很多子module。这些module之间存在各种相互依存的关系。有负责提供底层功能,有负责提供组件间通信,也有的本身就是业务组件。
  • 这些模块,除了Project中的app之外,实际上在编译之后,都不会成为一个apk的形式存在。
  • 大部分时候,这些模块,都会以aar或者jar包的方式,依赖到app模块中,最后在被编译到apk里运行。

##初始化问题

  • 既然module增加了,就肯定涉及到各个module的初始化。比如埋点模块,热更新模块等等。这些模块有些是单例运行的,需要在初始化的时候,注入Application或者ApplicationContext。
  • 基本上来说,组件化的初始化问题,就是需要频繁手动地针对每一个module,调用初始化函数,注入ApplicationContext等等相同的操作。
  • 这些操作,对于只有简单的几个module的Project,大可手动编写就好了。但是往往组件化大型系统,产生的module就会非常多,而如果这些事情都交给开发人员自己把控,会出现以下问题:
    • 代码规范(组件化module初始化的代码风格统一,有利于可读性)
    • 自动化处理可能更不容易出错,毕竟module的初始化操作虽然不会频繁修改,但是减少犯错可能还是很必要的。

##插桩实现module的初始化功能

  • 如果我们定义好一个接口,让每一个子module都做一个接口实现类,这个类在编译过程中我们通过字节码插桩的方式,将它初始化到app模块的Application类中,就能简单实现module的自动初初始化工作了。

##定义接口

  • 接口其实很简单,定义好在Application的需要分发的回调接口就好:
interface IModuleInitTemplate {

    @MethodExit
    fun attachBaseContextMethodExit(application: Application)

    @MethodEnter
    fun onCreateMethodEnter()

    @MethodExit
    fun onCreateMethodExit()
}

 评论