kotlinでaspectjaopを使用したいのですが、コードは次のとおりです。
annotation.lazy_listの私の注釈:
Kotlin:
package anotation
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class lazy_list
私のアスペクト指向クラス:
@Aspect
class ActiveListAop{
@Pointcut("execution(@annotation.lazy_list * *(..))")
fun profile() {
}
@Before("profile()")
fun testModeOnly(joinPoint: JoinPoint) {
println("123")
}
}
私の使用法:
@lazy_list
fun all():List<T>{
return lazy_obj?.all() as List<T>
}
all()関数を呼び出すと、エラーは発生しませんが、「123」が出力されないのはなぜですか?
Kotlinでの注釈プロセスでは、 [〜#〜] kapt [〜#〜] を有効にして使用する必要があります。これがGradleまたはMavenプラグインを介して追加されない限り、Kotlinコードでの注釈処理には何も機能しません。
Kotlinプラグインは、DaggerやDBFlowなどの注釈プロセッサをサポートしています。それらがKotlinクラスで動作するようにするには、kotlin-kaptプラグインを適用します。
参照:
spring + kotlin + AOPの動作いいですね。 http://start.spring.io/ にアクセスして、AOPをサポートするプロジェクトを生成すると、ビルドの一部が表示されます。 gradle ここ...
buildscript {
ext {
kotlinVersion = '1.2.30'
springBootVersion = '2.0.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
}
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'org.springframework.boot'
...
dependencies {
compile('org.springframework.boot:spring-boot-starter-aop')
...
}
プラグイン kotlin-spring は、すべてのクラスをopenにしてAOPを許可します
次に、次のようにアスペクトを宣言します
@Aspect
@Component
class MyAspect {
...
重要:アスペクトクラスに @ Aspect および @ Component アノテーションを付けます
ケーキ! :)
その価値のために、AndroidプロジェクトでaspectJウィービングが必要でしたが、本当にkotlinに移行したかったので、この問題を解決する必要がありました。したがって、springまたはmavenを使用したこのスレッドのソリューションは解決しませんでした。これはAndroid gradleプロジェクトの解決策ですが、これによりインクリメンタルコンパイルが中断されるため、ビルド時間が遅くなったり、最終的に何かが中断したりします。 -私たちのアーキテクチャを考えて、aspectJを段階的に廃止するか、(うまくいけば)Androidがサポートを開始します。
Kaptがこれを解決するOPへの回答とコメントのいくつかには混乱がありますが、kaptを使用すると、ウィービングではなく、コンパイル時の注釈処理を実行できます。つまり、注釈プロセッサを使用すると、注釈に基づいてコードを生成できますが、既存のコードにロジックを挿入することはできません。
これは、AndroidへのaspectJの追加に関するこのブログの上に構築されています: https://fernandocejas.com/2014/08/03/aspect-directiond-programming-in-Android
Kotlinクラスは、別のディレクトリにあるバイトコードにコンパイルされます。したがって、このソリューションは同じプロセスを使用してJavaクラスを織りますが、kotlinクラスファイルで再度実行します
App/build.gradle
の上部に追加:
buildscript {
ext.aspectjVersion = '1.9.1'
dependencies {
classpath "org.aspectj:aspectjtools:$aspectjVersion"
}
}
App /build.gradleの下部に次を追加します。
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
}
}
}
}
@RobbyCornelissenの答えを確認してください ここ 。私はそれがうまくいくことを発見しました、そして彼に感謝します。