Skip to content

常见问题

FlyJingFish edited this page Sep 19, 2024 · 67 revisions

1、 同一个方法存在多个注解或匹配切面时,怎么处理的

  • 多个切面叠加到一个方法上时注解优先于匹配切面,注解切面之间从上到下依次执行
  • 调用 proceed 才会执行下一个切面,多个切面中最后一个切面执行 proceed 才会调用切面方法内的代码
  • 在前边切面中调用 proceed(args) 可更新方法传入参数,并在下一个切面中也会拿到上一层更新的参数
  • 存在异步调用proceed时,第一个异步调用 proceed 切面的返回值(就是 invoke 的返回值)就是切入方法的返回值;否则没有异步调用proceed,则返回值就是最后一个切面的返回值

2、Build时报错 "ZipFile invalid LOC header (bad signature)"

  • 请重启Android Studio,然后 clean 项目

3、 切面处理类发生内存泄漏?

  • 这种情况一般是因为你在切面处理类做了强引用

4、 想要看到所有的加入切面代码的位置

plugins {
    ...
}
androidAopConfig {
    //默认关闭,开启在 Build 或 打包后 将会生成切点信息json文件在 app/build/tmp/cutInfo.json
    cutInfoJson true
}
android {
    ...
}

5、想要在方法前后插入代码

  • 匹配切面
@AndroidAopMatchClassMethod(
        targetClassName = "com.flyjingfish.test_lib.TestMatch",
        methodName = ["test2"],
        type = MatchType.SELF
)
class MatchTestMatchMethod : MatchClassMethod {
  override fun invoke(joinPoint: ProceedJoinPoint, methodName: String): Any? {
    //在方法前插入代码
    val value = joinPoint.proceed()
    //在方法后插入代码
    return value
  }
}
点此看更多详情🔴
  • 注解切面
class CustomInterceptCut : BasePointCut<CustomIntercept> {
    override fun invoke(
        joinPoint: ProceedJoinPoint,
        annotation: CustomIntercept //annotation就是你加到方法上的注解
    ): Any? {
        //在方法前插入代码
        val value = joinPoint.proceed()
        //在方法后插入代码
        return value
    }
}
  • 替换切面
@AndroidAopReplaceClass("android.util.Log")
object ReplaceLog {
    @AndroidAopReplaceMethod("int e(java.lang.String,java.lang.String)")
    @JvmStatic
    fun e( tag:String, msg:String) :Int{
        //在方法前插入代码
        val log = Log.e(tag, "ReplaceLog-$msg")
        //在方法后插入代码
        return log
    }
}

6、匹配切面和注解切面的切面处理类的生命周期是怎样的?

切面处理类与类的对应方法绑定在一起,分为两种情况

  • a、如果切点方法 不是静态的
    • 切面处理类会随着方法所在对象的回收而回收,但这不是及时的;回收时机是其他任意一个切面处理时才进行回收。
    • 并且每一个对象的切点方法各自对应一个切面处理类的对象,也就是说一个切点方法的所在类创建了多少个对象,就有多少个切面处理类对象。
  • b、如果切点方法 是静态的
    • 切面方法因为是静态的,所以切面处理类一旦被创建会一直存在。
    • 并且一个类方法只对应一个切面处理类

不管是a、b哪种类型,切面处理类对象只有在方法被执行时才会被创建出来。

简单来说,切面处理类的对象和类或类的对象是绑定在一块的,它的生命周期略长于切点非静态方法的类的对象。

这与 Aspectj 是不同的,因为我们往往想在切面处理类中设置一些成员变量,方便在下次切面处理时的使用;而 Aspectj 你要想这么做是需要将“成员变量”保存为一个“静态变量”,而且还需要区分执行切点方法的对象是什么,需要写很多的代码,AndroidAOP 刚好优化解决了这一问题。

7、Windows电脑编译报错或提示文件占用

  • 1、你先尝试升级 Gradle8.7 以上 能否解决

image

  • 2、然后保证是本库是最新版,然后保证 app 模块的 build.gradleid 'android.aop' 在最后一行
image
  • 3、否则请按如下步骤进行尝试(⚠️⚠️⚠️请注意以下只针对 Windows 电脑,mac电脑不应有此问题)
点此展开查看详情🔴
  • 0、首先确保直接运行 ./gradlew --stop 能否成功,如果失败请自行上网查询,然后再进行下边的步骤 image

  • 1、点开运行配置 6b8df9add79f183b5af3357b8ee6951e

  • 2、在原来基础上,新增 Run External tool 任务类型 image

  • 3、按如下配置—————— a769abbe58f17d6a02f8a0e27965f359

参数:
Program: 项目所在的绝对路径\gradlew.bat
Arguments: ./gradlew --stop
Working directory: 项目所在的绝对路径\

  • 4、把顺序调整到上边 image

  • 5、点击ok完成 image

  • 6、直接跑项目,出现以下情况,即代表配置成功 0e441acab958a77ccf7282d5473417a5

  • 7、另外有些网友提到把 ksp 换成 kapt 也可以解决问题

8、“Caused by: java.lang.SecurityException: digest error” 相关报错 (1.5.5版本已修复该bug,建议优先升级处理)

点此展开查看详情🔴

你新增的 jar 包中包含以下文件,请将其删除,改为本地导入 jar 包

show

操作步骤

  • 1、打开 jar 包所在目录cd /Users/a111/Downloads/ida-android-new/app/libs

  • 2、解压 jar 包 jar -xvf bcprov-jdk15on-1.69.jar

show
  • 3、解压后
show
  • 4、打开 META-INF 删除以下文件
show
  • 5、打包,之后可以用了jar -cfm0 bcprov-jdk15on-1.69.jar META-INF/MANIFEST.MF org
show

9、为什么我开启了 androidAop.debugMode = true 依然感觉打包编译慢?

造成这种情况的主要原因在于你可能用到了一些 Router 库,或者其他改变打包方式的插件。您可参考这里去改造你的项目点此前往,这里演示了如何去除这些库的插件部分,用 AndroidAOP 去完成它的插件的工作,这样你就可以删掉这些插件加快打包速度

10、可变参数如何进行匹配?

Kotlin 中的 vararg str : String 相当于 Java 中的 String...,这种匹配时无论哪种代码都按 String[] 来表示(此处以 String 为例,其他类型也一样)

11、加入本库之后安装app时提示找不到文件

检查你的 build.gradle 中配置中是否包含中文,如存在中文请尝试更改为英文后再次安装

12、在 @AndroidAopReplaceMethod 注解的方法中调用原方法会不会造成递归的情况?

  • 如果是直接调用就不会造成递归,框架已作处理

  • 如果属于间接调用就会造成递归,例如调用包含的原方法的其他类的方法,框架对此不做处理,如需这么做可以结合 exclude 来使用首页接入第四步有介绍,使用exclude排除掉间接调用类即可

13、只想引入 android-aop-annotation 这个库的话,怎么办?

请升级至 2.1.5及之后的版本