如何使用 gradle 每次都使用 aspect weave kotlin 代码
How to make aspect weave kotlin code every time with gradle
我正在研究 AOP 并使用 gradle + aspectJ 来编写我的代码。所以我按照一些演示所说的那样,将 aspectJtools 添加到顶部 build.gradle.
dependencies {
...
classpath 'org.aspectj:aspectjtools:1.9.5'
}
并在app/build.gradle中,添加任务编织代码:
variants.all { variant ->
JavaCompile javaCompile
if (variant.hasProperty('javaCompileProvider')) {
//android gradle 3.3.0 +
javaCompile = variant.javaCompileProvider.get()
} else {
javaCompile = variant.javaCompile
}
def buildType = variant.buildType.name
javaCompile.doLast {
MessageHandler handler = new MessageHandler(true)
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)
]
new Main().run(javaArgs, handler)
String[] kotlinArgs = [
"-showWeaveInfo",
"-1.8",
"-inpath", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,
"-aspectpath", javaCompile.classpath.asPath,
"-d", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)
]
new Main().run(kotlinArgs, handler)
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
}
}
}
}
然后我添加我的方面:
@Aspect
public class AspectInCommon extends BaseAspect {
@Pointcut("execution(* com.example.cheng.test.MainActivityKt.on**(..))")
public void kotlinMainOn() {
}
@After("kotlinMainOn()")
public void hookKotlinMain(JoinPoint joinPoint) throws Throwable {
log(joinPoint.getSignature().toLongString());
}
...
}
我的 MainActivity 看起来像:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
}
}
通过这种方式,我确实将方面融入了我的代码。这是一些输出:
它第一次工作正常,直到我再次单击调试底部,然后所有输出都不再触发。然后经过几次测试,我发现如果我的文件之一在 kotlin 中,它只会在干净构建后编织。所以我尝试将 mainActivity 和 aspect 文件更改为 java 或 kotlin。这是测试结果:
MainActivity language Aspect language Weave results
Java Java Weave every time
Java Kotlin Weave after clean build *
Kotlin Java Weave after clean build
Kotlin Kotlin Weave after clean build
*:我将方面文件放在子模块中,它在干净构建后的第二次构建中崩溃了。错误信息是:
java.lang.NoSuchMethodError: No static method aspectOf()
我想知道如何每次都对 kotlin 代码进行方面编织,而不是在干净构建后只编织一次,因为我实际项目的大部分代码都是基于 kotlin 的。不简单地使用插件是完美的。非常感谢。
我既不使用 Gradle(而是 Maven)也不使用 Kotlin,但我使用多种 JVM 语言或多个编译步骤的经验表明,在单独的模块中执行每个编译步骤是有意义的。
- 所以你可以有一个 Java + Kotlin 应用程序 class 模块,用普通的 Java/Kotlin 编译器编译它。
- 然后你有一个用 AspectJ 编译器编译的方面模块。
- 最后,有一个模块使用 AspectJ 进行二进制编织,在 inpath 上使用第一个模块,在 aspect 路径上使用第二个模块。
这使得构建更简单、更稳定。其他优势是您拥有一个原始的、未编织的应用程序模块和一个方面增强的应用程序模块。根据情况,您可以在应用程序中使用前者或后者,例如如果你编织不应该总是使用的调试或跟踪方面。最后但同样重要的是,一个单独的方面模块使方面库有可能被重用。
我正在研究 AOP 并使用 gradle + aspectJ 来编写我的代码。所以我按照一些演示所说的那样,将 aspectJtools 添加到顶部 build.gradle.
dependencies {
...
classpath 'org.aspectj:aspectjtools:1.9.5'
}
并在app/build.gradle中,添加任务编织代码:
variants.all { variant ->
JavaCompile javaCompile
if (variant.hasProperty('javaCompileProvider')) {
//android gradle 3.3.0 +
javaCompile = variant.javaCompileProvider.get()
} else {
javaCompile = variant.javaCompile
}
def buildType = variant.buildType.name
javaCompile.doLast {
MessageHandler handler = new MessageHandler(true)
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)
]
new Main().run(javaArgs, handler)
String[] kotlinArgs = [
"-showWeaveInfo",
"-1.8",
"-inpath", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,
"-aspectpath", javaCompile.classpath.asPath,
"-d", project.buildDir.path + "/tmp/kotlin-classes/" + buildType,
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)
]
new Main().run(kotlinArgs, handler)
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
}
}
}
}
然后我添加我的方面:
@Aspect
public class AspectInCommon extends BaseAspect {
@Pointcut("execution(* com.example.cheng.test.MainActivityKt.on**(..))")
public void kotlinMainOn() {
}
@After("kotlinMainOn()")
public void hookKotlinMain(JoinPoint joinPoint) throws Throwable {
log(joinPoint.getSignature().toLongString());
}
...
}
我的 MainActivity 看起来像:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
}
}
通过这种方式,我确实将方面融入了我的代码。这是一些输出:
MainActivity language Aspect language Weave results
Java Java Weave every time
Java Kotlin Weave after clean build *
Kotlin Java Weave after clean build
Kotlin Kotlin Weave after clean build
*:我将方面文件放在子模块中,它在干净构建后的第二次构建中崩溃了。错误信息是:
java.lang.NoSuchMethodError: No static method aspectOf()
我想知道如何每次都对 kotlin 代码进行方面编织,而不是在干净构建后只编织一次,因为我实际项目的大部分代码都是基于 kotlin 的。不简单地使用插件是完美的。非常感谢。
我既不使用 Gradle(而是 Maven)也不使用 Kotlin,但我使用多种 JVM 语言或多个编译步骤的经验表明,在单独的模块中执行每个编译步骤是有意义的。
- 所以你可以有一个 Java + Kotlin 应用程序 class 模块,用普通的 Java/Kotlin 编译器编译它。
- 然后你有一个用 AspectJ 编译器编译的方面模块。
- 最后,有一个模块使用 AspectJ 进行二进制编织,在 inpath 上使用第一个模块,在 aspect 路径上使用第二个模块。
这使得构建更简单、更稳定。其他优势是您拥有一个原始的、未编织的应用程序模块和一个方面增强的应用程序模块。根据情况,您可以在应用程序中使用前者或后者,例如如果你编织不应该总是使用的调试或跟踪方面。最后但同样重要的是,一个单独的方面模块使方面库有可能被重用。