基于ksp生成描述文件的方法及快速插桩的gradle编译系统转让专利

申请号 : CN202211611995.6

文献号 : CN115617353B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 沈黎明叶玎玎骆晓广张溪梦张金银

申请人 : 杭州比智科技有限公司

摘要 :

本发明公开了一种基于ksp生成描述文件的方法及快速插桩的gradle编译系统,其中方法包括如下步骤:声明配置描述文件的自定义注解及其属性字段;根据自定义注解对需要注入的类进行描述,以自定义描述接口类;根据描述接口类,通过ksp自动生成不同插桩类型的实体集合,实体集合中包括需要插桩的类名,方法和位置;根据插桩的实体集合通过Gradle编译期间对代码进行快速自动插桩。本发明通过在接口描述文件上声明插桩的目标,方法和位置,方便直接观测到所有插桩的描述,能够自动的生成所有需要插桩的类路径和方法,能够自动在编译期间对代码进行插桩,能够大幅提高项目编译开发的效率。

权利要求 :

1.一种基于 ksp 生成描述文件的方法,其特征在于,所述方法包括以下步骤:S1.声明配置描述文件的自定义注解及其属性字段;根据不同类型的插桩情况分别对应创建多种类型注解和一种通用型注解;并设置标识注解Belong来提供给ksp进行识别;

S2.根据自定义注解对需要注入的类进行描述,以自定义描述接口类;由标识注解Belong声明接口描述文件,相应注解属性声明该接口描述文件将要插桩的代码类路径;

S3.根据描述接口类,通过ksp自动生成不同插桩类型的类路径方法的集合;

S4.根据插桩的实体集合通过 Gradle 编译期间对代码进行快速插桩;通过AGP读取实体集合,遍历所有的用户代码和第三方jar包,与内存中的实例集合进行匹配,对代码进行插桩处理,将插桩后的代码同项目一起打包进行发布;

步骤S3中包括以下子步骤:

S301,注册KSP处理器,遍历所有有Belong标识注解的接口描述类,处理包含Belong表示注解的接口;

S302,遍历所有配置描述文件获取注解上的信息,该实体为Kotlin中的对象实例;

S303,将数据实体根据插桩类型放入不同的集合中;

S304,通过KotlinPoet生成实体集合类;其中生成类为 HookInjectorClass,该Class为静态的kotlin类,能在 gradle 插件中直接调用;

S305,通过 Gradle 自定义任务自动将生成的类复制到Gradle插件中;其中任务会自动在build时运行,保证每一次改动都能在编译时自动实时更新。

2. 根据权利要求1所述的基于 ksp 生成描述文件的方法,其特征在于,步骤S1中声明配置描述文件的自定义注解及其属性字段,包括:S101.根据不同的插桩方式和位置声明各种类型的自定义注解;

S102.通过注解属性声明插桩目标的类和方法。

3.根据权利要求2所述的方法,其特征在于,步骤S101中,所述不同的插桩方式包括插入插入目标类的目标方法、插入目标类的目标方法调用时的上下行和插入目标类其一级子类的目标方法。

4.根据权利要求2所述的方法,其特征在于,步骤S102中,通过注解属性声明插桩目标的类和方法,包括:声明目标类,目标方法,方法参数,返回值,位置前后,插桩目标属性以确定插桩位置的唯一性。

5.根据权利要求1所述的方法,其特征在于,步骤S2中,根据自定义注解对需要注入的类进行描述以自定义描述接口类,包括:S201.根据需要插桩的类和插桩的类型选择特定类型的注解并填写注解属性,可根据不同的功能类型分为不同的描述接口类;

S202.根据不同的插桩类型生成不同的实体集合,用于 Gradle 编译通过类型采取不同措施。

6.根据权利要求1所述的方法,其特征在于,步骤S304中通过KotlinPoet自动生成的代码需要预先定好模板代码,具体包括以下子步骤:S304.1利用ClassBuilder构造一个包含所有插桩参数的实体类;

S304.2利用PropertySpecBuilder初始化集合,用来存放步骤S304.1生成的实体类;

S304.3利用FunSpecBuilder生成行代码,循环将步骤S302解析获得的参数封装并放入集合中;S304.4生成名为HookInjectorClass的类文件。

7.一种快速插桩的gradle编译系统,其特征在于,所述系统用于实现根据权利要求1‑6任一项所述的方法,系统包括:声明模块,根据自定义注解对需要注入的类进行描述,以自定义描述接口类;

文件生成模块,在预编译期间通过ksp生成不同插桩类型的实体集合;

插桩模块,根据实体集合通过 Gradle 编译期间对代码进行遍历插桩。

8.根据权利要求7所述的快速插桩的gradle编译系统,其特征在于,所述声明模块包括:注解子单元,用于声明配置描述文件的自定义注解及其属性字段;

描述文件子单元,根据自定义注解对需要注入的类进行描述以自定义描述接口类。

9.根据权利要求7所述的快速插桩的gradle编译系统,其特征在于,所述文件生成模块用于:通过ksp生成不同插桩类型的实体集合,每个实体里面包含目标类路径、目标方法、目标参数、注入类路径、注入方法、注入参数和位置前后。

10.根据权利要求7所述的快速插桩的gradle编译系统,其特征在于,所述插桩模块用于:根据生成的实体集合类,该集合类包含所有的需要插桩的类方法和位置;Gradle在编译期间根据该集合类对代码进行遍历插桩。

说明书 :

基于ksp生成描述文件的方法及快速插桩的gradle编译系统

技术领域

[0001] 本发明涉及计算机技术领域,特别涉及一种基于ksp生成描述文件的方法及快速插桩的gradle编译系统。

背景技术

[0002]  Kotlin(科特林)是一个用于现代多平台应用的静态编程语言,由 JetBrains 公司开发,它可以被编译成多种语言在不同的机器上运行。现已作为安卓开发的官方语言。Ksp (Kotlin Symbol Processing 谷歌的基于Kotlin编译器提供的符号处理工具)是新一代的 Kotlin 注解处理工具,它基于 Kotlin 编译器实现,相对于 KAPT(可插入式注解处理Kotlin版)性能得到很大提升。Android Gradle 是开发安卓的默认构建工具,它提高了安卓的开发效率,能管理项目中的依赖、打包和编译。代码插桩指在目标程序代码编译的过程中某些位置插入或修改成一些代码,从而在目标程序运行过程中获取某些程序状态并加以分析,即代码中插入代码。
[0003] 目前代码插桩的技术方案都是在 Gradle 编译期间手动编写需要插桩的代码类路径,方法和参数等一系列配置,每次修改都需要技术人员完全熟悉编译开发的技术细节和代码逻辑,同时还不能直接的观测到所有代码插桩的类路径和方法,极其容易发生错误和影响开发效率。

发明内容

[0004] 针对现有技术存在的问题,本发明的目的在于通过在接口描述文件上声明插桩的目标,方法和位置,方便直接观测到所有插桩的描述,能够自动的生成所有需要插桩的类路径和方法,能够自动在编译期间对代码进行插桩,能够大幅提高项目编译开发的效率。
[0005] 为实现上述目的,本发明提供一种基于ksp生成描述文件的方法,所述方法包括以下步骤:
[0006] S1.声明配置描述文件的自定义注解及其属性字段;根据不同类型的插桩情况分别对应创建多种类型注解和一种通用型注解;并设置标识注解Belong来提供给ksp进行识别;
[0007] S2.根据自定义注解对需要注入的类进行描述,以自定义描述接口类;由标识注解Belong声明接口描述文件,相应注解属性声明该接口描述文件将要插桩的代码类路径;
[0008] S3.根据描述接口类,通过ksp自动生成不同插桩类型的类路径方法的集合;
[0009] S4.根据插桩的实体集合通过Gradle 编译期间对代码进行快速插桩;通过AGP读取实体集合,遍历所有的用户代码和第三方jar包,与内存中的实例集合进行匹配,对代码进行插桩处理,将插桩后的代码同项目一起打包进行发布。
[0010] 进一步,步骤S1中声明配置描述文件的自定义注解及其属性字段,包括:
[0011] S101.根据不同的插桩方式和位置声明各种类型的自定义注解;
[0012] S102.通过注解属性声明插桩目标的类和方法。
[0013] 进一步,步骤S101中,所述不同的插桩方式包括插入插入目标类的目标方法、插入目标类的目标方法调用时的上下行和插入目标类其一级子类的目标方法。
[0014] 进一步,步骤S102中,通过注解属性声明插桩目标的类和方法,包括:
[0015] 声明目标类,目标方法,方法参数,返回值,位置前后,插桩目标属性以确定插桩位置的唯一性。
[0016] 进一步,步骤S2中,根据自定义注解对需要注入的类进行描述以自定义描述接口类,包括:
[0017] S201.根据需要插桩的类和插桩的类型选择特定类型的注解并填写注解属性,可根据不同的功能类型分为不同的描述接口类;
[0018] S202.根据不同的插桩类型生成不同的实体集合,用于Gradle 编译通过类型采取不同措施。
[0019] 进一步,步骤S3中包括以下子步骤:
[0020] S301,注册KSP处理器,遍历所有有Belong标识注解的接口描述类,处理包含Belong表示注解的接口;
[0021] S302,遍历所有配置描述文件获取注解上的信息,该实体为Kotlin中的对象实例;
[0022] S303,将数据实体根据插桩类型放入不同的集合中;
[0023] S304,通过KotlinPoet生成实体集合类;其中生成类为HookInjectorClass,该Class为静态的kotlin类,能在gradle插件中直接调用;
[0024] S305,通过 Gradle 自定义任务自动将生成的类复制到Gradle插件中;其中任务会自动在build时运行,保证每一次改动都能在编译时自动实时更新。
[0025] 另一方面,本发明提供一种快速插桩的gradle编译系统,所述系统用于实现根据本发明所述的方法,系统包括:
[0026] 声明模块,根据自定义注解对需要注入的类进行描述,以自定义描述接口类;
[0027] 文件生成模块,在预编译期间通过ksp生成不同插桩类型的实体集合;
[0028] 插桩模块,根据实体集合通过Gradle 编译期间对代码进行遍历插桩。
[0029] 进一步,所述声明模块包括:
[0030] 注解子单元,用于声明配置描述文件的自定义注解及其属性字段;
[0031] 描述文件子单元,根据自定义注解对需要注入的类进行描述以自定义描述接口类。
[0032] 进一步,所述文件生成模块用于:
[0033] 通过ksp生成不同插桩类型的实体集合,每个实体里面包含目标类路径、目标方法、目标参数、注入类路径、注入方法、注入参数和位置前后。
[0034] 进一步,所述插桩模块用于:
[0035] 根据生成的实体集合类,该集合类包含所有的需要插桩的类方法和位置;Gradle在编译期间根据该集合类对代码进行遍历插桩。
[0036] 本发明实施例通过在接口描述文件上声明插桩的目标,方法和位置,能够高效率的对代码进行插桩,大幅提高了项目编译开发的效率。

附图说明

[0037] 图1示出了根据本发明实施例中基于ksp生成描述文件方法的流程示意图;
[0038] 图2示出了本发明实施例中的Ksp注解处理接口描述类的过程流程图;
[0039] 图3示出了Android Gradle 插件在编译期间对代码进行插桩的流程图;
[0040] 图4示出了本发明实施例的快速插桩的gradle编译系统结构示意图。

具体实施方式

[0041] 下面将结合附图,对本发明的技术方案进行清楚、完整地描述,显然,所描述的实施例是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
[0042] 在本发明的描述中,需要说明的是,术语“中心”、“上”、“下”、“左”、“右”、“竖直”、“水平”、“内”、“外”等指示的方位或位置关系为基于附图所示的方位或位置关系,仅是为了便于描述本发明和简化描述,而不是指示或暗示所指的装置或元件必须具有特定的方位、以特定的方位构造和操作,因此不能理解为对本发明的限制。此外,术语“第一”、“第二”、“第三”仅用于描述目的,而不能理解为指示或暗示相对重要性。
[0043] 在本发明的描述中,需要说明的是,除非另有明确的规定和限定,术语“安装”、“相连”、“连接”应做广义理解,例如,可以是固定连接,也可以是可拆卸连接,或一体地连接;可以是机械连接,也可以是电连接;可以是直接相连,也可以通过中间媒介间接相连,可以是两个元件内部的连通。对于本领域的普通技术人员而言,可以根据具体情况理解上述术语在本发明中的具体含义。
[0044] 以下结合图1‑图4对本发明的具体实施方式进行详细说明。应当理解的是,此处所描述的具体实施方式仅用于说明和解释本发明,并不用于限制本发明。
[0045] 如图1所示,本发明实施例提供的基于ksp生成描述文件方法包括如下步骤S1‑步骤S4。
[0046] S1.声明配置描述文件的自定义注解及其属性字段;
[0047] S2.根据自定义注解对需要注入的类进行描述,以自定义描述接口类;
[0048] S3.根据描述接口类,通过ksp生成不同插桩类型的实体集合;
[0049] S4.根据插桩的实体集合通过Gradle 编译期间对代码进行快速插桩。
[0050] 具体的,步骤S1声明配置描述文件的自定义注解及其属性字段包括以下子步骤:
[0051] S101.根据不同的插桩方式和位置声明各种类型的自定义注解;
[0052] S102.通过注解属性声明插桩目标的类和方法。
[0053] 首先,步骤S101中,关于不同的插桩方式,为了能够适配不同情况下的插桩情况,可以将代码插入的情况分为三种情况:一是插入目标类的目标方法中,这种也是最常用的代码插入方式;二是插入目标类的目标方法调用时的上下行,这样能够检测到目标的调用频次;三是插入目标类其一级子类的目标方法中,目的是为了防止在多重继承情况下的多次代码注入。根据这三种情况,本发明分别对应创建了三种类型注解,分别为TargetInject,AroundInject和SuperInject和一种通用型注解Inject。同时设置标识注解(Belong)来提供给ksp进行识别,该注解包含一个className字段,用来声明插桩代码的路径地址。类型注解中包含多个字段用来声明目标类的路径、方法等,多个字段具体为:clazz对应目标类的路径、method对应目标类的方法、parameterTypes对应目标方法的参数描述、returnType对应目标方法的返回类型、isAfter对应插桩位置的前后。通用注解(Inject)字段分别为:targetClazz表示目标类路径、targetMethod表示目标类的方法、
targetMethodDesc表示目标方法的参数、injectMethod表示插入类的方法、
injectMethodDesc表示插入方法的参数描述、isAfter表示插桩位置的前后、type表示插桩类型对应上述三种注解类型。声明注解是对注入类进行描述的前提,下一步骤为使用这些注解配置描述文件。
[0054] S2,根据自定义注解对需要注入的类进行描述,以自定义描述接口类。
[0055] 具体地,S2中包括子步骤:
[0056] S201.根据需要插桩的类和插桩的类型选择特定类型的注解并填写注解属性,可根据不同的功能类型分为不同的描述接口类;
[0057] S202.根据不同的插桩类型生成不同的实体集合,用于Gradle 编译通过类型采取不同措施。
[0058] 具体的,由标识注解(Belong)声明接口描述文件,字段className声明该接口描述文件将要插桩的代码类路径。接下来接口描述文件中的每个方法都需要类型注解声明该方法是需要通过Gradle编译时插桩注入的。为了不让代码混淆,每一个接口描述文件都只针对一个插桩功能模块。所有的描述文件都应在同一个地方,这样方便开发者能够观测到所有插桩的描述以及对其修改。
[0059] S3,根据描述接口类,通过ksp生成不同插桩类型的实体集合。
[0060] 具体的,通过 ksp 读取所有接口描述文件并在Gradle预编译前生成一个实体类集合。ksp会解析源码并生成AST树型结构,同时会提供一个 Resolver(解释器)使用访问者模式去遍历解析 AST 结构树上的符号,包括访问类中的所有成员方法,判断一个类或者方法是否是局部类或局部方法,判断一个类成员是否对其他成员可见和获取注解信息等。本实施实例中就是通过ksp解释器能够获取接口类的注解信息的原理来进行实现自动类的生成。
[0061] 如图2所示,为本发明实施例中的Ksp注解处理接口描述类的过程流程图。具体包括如下子步骤:
[0062] S301,注册ksp处理器,它会遍历所有包含Belong标识注解的接口描述类,只有包含Belong表示注解的接口才会被处理器处理。
[0063] 具体的,在ksp处理器中,利用Resolver可以得到目标注解的KSClassDeclaration(类声明),本实例实施中可以得到Belong注解的类声明,而非Belong注解的声明都可以过滤掉不处理。
[0064] S302,处理器会通过解释器获取到接口类上每一个注解上的参数并生成数据实体。该生成的数据实体为Kotlin中的对象实例,实例中包含了接口描述文件的所有字段属性,能将注解的参数一一映射到实例中。
[0065] 具体的,前面已经得到的Belong注解的KSClassDeclaration(类声明)中进一步解析可以得到在配置描述文件中的参数。KSClassDeclaration上的Annotations的参数即为需要插桩位置InjectClass。
[0066] KSClassDeclaration上的DeclaredFunctions能解析出来所有方法,每个方法Function包括方法名Name,方法参数Params和方法注解Annotation。解析方法名需要调用Function的getName(),得到的值为插桩的方法名InjectMethod。解析方法参数通过
Function的getParameters()获得,拿到KSTypeReference参数类型,但此时还需要将
Kotlin类型的参数处理成Java参数类型,这里涉及到KSType的类型转化,常见的基本类型转化为:Lkotlin/Unit;=>V(无参);Lkotlin/Int;=>I(整数类型);Lkotlin/Byte;=>B(字节类型);Lkotlin/Boolean;=>Z(布尔类型);Lkotlin/Char;=>C(字符类型);Lkotlin/Short;
=>S(短整数类型);Lkotlin/Float;=>F(浮点数类型);Lkotlin/Long;=>J(长整数类型);
Lkotlin/Double;=>D(双精度浮点数类型);Lkotlin/Any;=>Ljava/lang/Object;除此之外对象实例的转化为包名+类名,数组则是一维数组[,二维数组[[,三维数组[[[…以此类推。
得到的值为InjectMethodDesc。Function上的注解内容是上述配置描述文件步骤中的设置的属性,通过Function的getAnnotations方法可以得到TargetClass,TargetMethod,
TargetMethodDesc和注解类型。至此,描述文件中的每一个方法都能被解析成生成kotlin对象实例的所需参数。
[0067] S303,将数据实体根据插桩类型放入不同的集合中。集合同类型注解一致分为三种,目标型集合对应TargetInject注解,上下文集合对应AroundInject注解,继承型集合对应SuperInject注解。
[0068] S304,通过KotlinPoet生成实体集合类,KotlinPoet是一个用于自动生成.kt源文件的Kotlin API 工具。使用它能够在代码中通过建造者模式生成类,不需要再手动的生成类。本实施实例中生成的类为 HookInjectorClass,该Class为静态的kotlin类,能在 gradle 插件中直接调用,包含了上一步骤中产生的所有实体集合。
[0069] 具体的,通过KotlinPoet自动生成的代码需要预先定好模板代码,它包括以下子步骤:
[0070] S304.1利用ClassBuilder构造一个包含所有插桩参数的实体类;
[0071] S304.2利用PropertySpecBuilder初始化集合,用来存放步骤S304.1生成的实体类;
[0072] S304.3利用FunSpecBuilder生成行代码,循环将S302解析获得的参数封装并放入集合中;
[0073] S304.4最后生成名为HookInjectorClass的类文件。
[0074] S305,通过 Gradle 自定义任务自动将生成的类复制到Gradle插件中。其中任务会自动在build时运行,保证每一次改动都能在编译时自动实时更新。
[0075] S4,根据插桩的实体集合通过 Gradle 编译期间对代码进行快速插桩。
[0076] 具体的,Android Gradle 自定义插件 (AGP) 是受支持的 Android 应用构建系统,支持编译多种不同类型的源代码,提供自动化处理流程。Gradle插件通过ASM(通用的Java字节码操作和分析框架)对项目中的代码以访问者模式进行解析,得到类的复杂结构对象可获取类的路径,方法,参数及返回值等属性,借此本实例可以匹配需要插桩的类。如图3所示,为自定义插件在编译期间对代码进行插桩的流程图。
[0077] S401,AGP会读取上述步骤产生的HookInjectorClass类中的实例集合,放入内存中方便快速读取。
[0078] S402,AGP开始遍历所有的用户代码,包括第三方jar包,与内存中的实例集合进行匹配,若是不匹配则跳过该类接下来的步骤,匹配则是开始对代码进行插桩处理。同时为了加快编译速度,会协同插件配置对类进行过滤。
[0079] 具体的,本实施示例使用了AGP在版本4.2后引入的Instrumentation API,AGP4.2版本之前的 Transform API 的项目会强制 AGP 对 build 使用优化程度不够的流程,从而导致构建时间大幅增加。新的Instrumentation API提高了完整 build 和增量 build 的性能,并使得调用接口变得简单,并且如果只在单个类中做出修改,则只有受影响的类在增量build中重新进行插桩,更加高效。同时为了避免过多的第三方库参与编译而拖慢整个编译过程,本实施示例中过滤了常见的第三方库和允许开发者在插件配置中由自己设置需要过滤的包名。
[0080] S403,InjectTargetClassVisitor:对目标类的目标方法进行插桩,处理目标型集合实例。
[0081] 具体的,首先在visit(字节码中的类遍历)中能获得类的具体名称和路径,通过和目标型集合继续比对;若匹配则继续往下遍历类中的方法‑visitMethod(字节码中的方法遍历),匹配方法名和方法参数;若匹配则可以对该方法进行代码的插桩。代码的插桩需要将集合中实体类中的所有参数转换为编译器可以识别的字节码,具体操作流程为:loadThis()将this压入内存栈顶;=>visitInsn(Opcodes.DUP)将栈顶的值复制一份并压入栈顶;=>loadLocal()获取当前方法的所有参数引用,便于插入代码时提供值;=>
invokeStatic传入插桩类路径和插桩类方法(包括类名称和参数)。至此一处代码的插入完成,后续需要遍历所有的类即可完成所有的代码插入。
[0082] S404,InjectAroundClassVisitor:在目标类的目标方法的上下行进行插桩,处理上下文集合实例。
[0083] 具体的,与S403不同的是需要在方法访问器中的visitMethodInsn()方法中遍历当前类的所有代码行来找到匹配的目标类和目标方法,找到匹配后继续插桩的流程,将参数转为编译器能识别的字节码。
[0084] S405,InjectSuperClassVisitor:插入目标类其一级子类的目标方法中,处理继承型集合实例。
[0085] 具体的,在Java中有类继承的概念,为了防止一处插桩同时在Java的父类和子类中重复插入,需要在进行类匹配的是当前类的SuperClass(父类)。若匹配则继续往下遍历类中的方法‑visitMethod(字节码中的方法遍历),匹配方法名和方法参数;若匹配则可以对该方法进行代码的插桩。代码的插桩需要将集合中实体类中的所有参数转换为编译器可以识别的字节码。
[0086] S406,完成编译后,插桩后的代码会自动同项目的代码一起打包进行发布。
[0087] 本发明实施例的快速插桩的gradle编译系统进行详细介绍,为了便于说明,仅示除了与本发明实施例相关的部分,具体技术细节未揭示的,请参照本发明上述所示的实施例。
[0088] 如图4所示,本发明实施例的项目结构示意图,本发明实施例的快速插桩的gradle编译系统4包括声明模块41,文件生成模块42和插桩模块43。
[0089] 其中声明模块41用于根据自定义注解对需要注入的类进行描述,以自定义描述接口类。声明模块41包括注解子单元411和描述文件子单元412。
[0090] 注解子单元411用于声明配置描述文件的自定义注解及其属性字段。
[0091] 具体的,首先为了能够适配不同情况下的插桩情况,可以将代码插入的情况分为三种情况:一是插入目标类的目标方法中,这种也是最常用的代码插入方式;二是插入目标类的目标方法调用时的上下行,这样能够检测到目标的调用频次;三是插入目标类其一级子类的目标方法中,目的是为了防止在多重继承情况下的多次代码注入。根据这三种情况,分别对应创建了三种类型注解(TargetInject,AroundInject,SuperInject)和一种通用型注解(Inject)。同时需要标识注解(Belong)来提供个ksp进行识别,该注解包含一个className字段,用来声明插桩代码的路径地址。类型注解中需要包含多个字段用来声明目标类的路径,方法等,具体为:clazz对应目标类的路径,method对应目标类的方法,parameterTypes对应目标方法的参数描述,returnType对应目标方法的返回类型,isAfter对应插桩位置的前后。通用注解(Inject)字段分别为:targetClazz表示目标类路径,targetMethod表示目标类的方法,targetMethodDesc表示目标方法的参数,injectMethod表示插入类的方法,injectMethodDesc表示插入方法的参数描述,isAfter表示插桩位置的前后,type表示插桩类型对应上述三种注解类型。
[0092] 描述文件子单元412用于根据自定义注解对需要注入的类进行描述,以自定义描述接口类。
[0093] 具体的,由标识注解(Belong)声明接口描述文件,字段className声明该接口描述文件将要插桩的代码类路径。接下来接口描述文件中的每个方法都需要类型注解声明该方法是需要通过Gradle编译时插桩注入的。为了不让代码混淆,每一个接口描述文件都只针对一个插桩功能模块。
[0094] 文件生成模块42用于根据描述接口类,通过ksp生成不同插桩类型的实体集合。
[0095] 具体的,Kotlin Symbol Processing 注解处理工具可以在Gradle编译前由声明描述类生成一个实体集合,集合同类型注解一致分为三种,目标型集合对应TargetInject注解,上下文集合对应AroundInject注解,继承型集合对应SuperInject注解。
[0096] 注解处理子单元421用于为本发明实施例中的Ksp注解处理接口描述类的过程。
[0097] 插桩模块43用于根据插桩的实体集合通过Gradle 编译期间对代码进行快速插桩。
[0098] 插桩模块43包括AGP编译子单元431,所述AGP编译子单元431为Android Gradle 插件在编译期间对代码进行插桩过程。AGP会读取生成的HookInjectorClass类中的实例集合,并借助ASM处理编译的代码,对目标类的目标方法进行插桩,完成编辑后,插桩后的代码会同项目一起打包进行发布。
[0099] 本发明流程图中或在此以其他方式描述的任何过程或方法描述可以被理解为表示包括一个或多个用于实现特定逻辑功能或过程的步骤的可执行指令的代码的模块、片段或部分,可以实现在任何计算机刻度介质中,以供指令执行系统、装置或设备,所述计算机可读介质可以是任何包含存储、通信、传播或传输程序以供执行系统、装置或设备使用。包括只读存储器、磁盘或光盘等。
[0100] 在本说明书的描述中,参考术语“实施例”、“示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本发明的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不必须针对的是相同的实施例或示例。此外,本领域的技术人员可以在不产生矛盾的情况下,将本说明书中描述的不同实施例或示例以及其中的特征进行结合或组合。
[0101] 上述内容虽然已经示出和描述了本发明的实施例,可以理解的是,上述实施例是示例性的,不能理解为对本发明的限制,本领域的普通技术人员在本发明的范围内可以对上述实施例进行变化、修改、替换和变型等更新操作。