Aspectj不适用于kotlin

jun*_*unk 9 aop aspectj kotlin

我想在kotlin中使用aspectj aop,这是我的代码:

我在annotation.lazy_list中的注释:

科特林:

 package anotation

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class lazy_list
Run Code Online (Sandbox Code Playgroud)

我的方面是一个类:

@Aspect
class ActiveListAop{

    @Pointcut("execution(@annotation.lazy_list * *(..))")
    fun profile() {

    }

    @Before("profile()")
    fun testModeOnly(joinPoint: JoinPoint) {
        println("123")
    }

}
Run Code Online (Sandbox Code Playgroud)

我的用法:

 @lazy_list
    fun all():List<T>{
        return lazy_obj?.all() as List<T>
    }
Run Code Online (Sandbox Code Playgroud)

当我调用all()函数,没有错误,但不打印"123",为什么?

bsa*_*ner 6

就其价值而言,我们需要在我们的 android 项目中使用 aspectJ,但我们真的很想迁移到 kotlin,所以我们必须解决这个问题。因此,该线程中使用 spring 或 maven 的解决方案对我们不起作用。这是 android gradle 项目的解决方案,然而,这将破坏增量编译,因此减慢您的构建时间和/或最终破坏某些东西。这让我们一直坚持到我可以重新思考我们的架构并逐步淘汰 aspectJ 或(希望)android 开始支持它。

对 kapt 解决此问题的 OP 的一些答案和评论存在混淆,但 kapt 可让您进行编译时注释处理,而不是编织。也就是说,注释处理器允许您根据注释生成代码,但不允许您将逻辑注入现有代码中。

这建立在这篇关于将 aspectJ 添加到 android 的博客之上:https ://fernandocejas.com/2014/08/03/aspect-orienting-programming-in-android

你的 kotlin 类被编译成字节码,只是到一个不同的目录中。所以这个解决方案使用相同的过程来编织 java 类,但在 kotlin 类文件上再次运行它

在您App/build.gradle添加的顶部:

buildscript {
    ext.aspectjVersion = '1.9.1'
    dependencies {
        classpath "org.aspectj:aspectjtools:$aspectjVersion"
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Jay*_*ard 5

对于Kotlin中的注释过程,您必须启用并使用KAPT.如果没有通过Gradle或Maven插件添加,Kotlin代码中的注释处理将无法正常工作.

Kotlin插件支持Dagger或DBFlow等注释处理器.为了让他们使用Kotlin类,请应用kotlin-kapt插件.

也可以看看:


小智 5

spring + kotlin + AOP 工作得很好,只需访问http://start.spring.io/并生成一个支持 AOP 的项目,你可以在这里看到一段build.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')
    ...
}
Run Code Online (Sandbox Code Playgroud)

插件kotlin-spring使所有类开放以允许 AOP

然后,只需按如下方式声明您的方面

@Aspect
@Component
class MyAspect {
...
Run Code Online (Sandbox Code Playgroud)

重要提示:使用@Aspect@Component注释来注释您的方面类

小菜一碟!:)

  • 问题是关于 **AspectJ** 而不是 Spring-AOP。除了仅适用于托管 bean 之外,Spring-AOP 与 AspectJ 相比还有其他限制。例如,它不支持编译时错误和警告声明。 (2认同)