项目中需要使用到 AOP 的功能,所以总结了一下在 Android 中使用 Aspectj 的方式。以下方案均可以在高等级的 Gradle + Kotlin 中使用,测试环境为 gradle 7.2 + kotlin 1.6.10
。
方案1:直接使用 Aspectj
https://stackoverflow.com/questions/44364633/aspectj-doesnt-work-with-kotlin/53320843#53320843
- at the top of your
App/build.gradle
add:
buildscript {
ext.aspectjVersion = '1.9.1'
dependencies {
classpath "org.aspectj:aspectjtools:$aspectjVersion"
}
}
- At the bottom of your
App/build.gradle
add:
android.applicationVariants.all { variant ->
// add the versionName & versionCode to the apk file name
variant.outputs.all { output ->
def newPath = outputFileName.replace(".apk", "-${variant.versionName}.${variant.versionCode}.apk")
outputFileName = new File(outputFileName, newPath)
def fullName = ""
output.name.tokenize('-').eachWithIndex { token, index ->
fullName = fullName + (index == 0 ? token : token.capitalize())
}
JavaCompile javaCompile = variant.javaCompiler
MessageHandler handler = new MessageHandler(true)
javaCompile.doLast {
String[] javaArgs = ["-showWeaveInfo",
"-1.8",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(
File.pathSeparator)]
String[] kotlinArgs = ["-showWeaveInfo",
"-1.8",
"-inpath", project.buildDir.path + "/tmp/kotlin-classes/" + fullName,
"-aspectpath", javaCompile.classpath.asPath,
"-d", project.buildDir.path + "/tmp/kotlin-classes/" + fullName,
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(
File.pathSeparator)]
new Main().run(javaArgs, handler)
new Main().run(kotlinArgs, handler)
def log = project.logger
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break
case IMessage.WARNING:
case IMessage.INFO:
log.info message.message, message.thrown
break
case IMessage.DEBUG:
log.debug message.message, message.thrown
break
}
}
}
}
方案2:使用 gradle-aspectj-pipeline-plugin
该方案是方案1的封装,只需要引入插件就可以使用,非常方便。
其他方案
另外调研了 Aspectjx,由于作者已经停止维护,所以放弃之。
结果
由于引入 Aspectj 之后,编译会报以下错误:
image.png所以最后没有使用 Aspectj,采用了其他方案。不知是否有该问题的解决方式?
网友评论