Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin Aspectj不';我不能和科特林一起工作_Kotlin_Aop_Aspectj - Fatal编程技术网

Kotlin Aspectj不';我不能和科特林一起工作

Kotlin Aspectj不';我不能和科特林一起工作,kotlin,aop,aspectj,Kotlin,Aop,Aspectj,我想在kotlin中使用aspectj aop,以下是我的代码: annotation.lazy_列表中的我的批注: 科特林: package anotation @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.FUNCTION) annotation class lazy_list 我的aspectj aop类: @Aspect class ActiveListAop{ @Pointcut("ex

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

annotation.lazy_列表中的我的批注:

科特林:

 package anotation

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class lazy_list
我的aspectj aop类:

@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>
    }
@lazy\u列表
fun all():列表{
将lazy_obj?.all()作为列表返回
}

调用all()函数时,没有错误,但不会打印“123”,为什么?

对于Kotlin中的注释过程,必须启用并使用。如果不通过Gradle或Maven插件添加此功能,Kotlin代码中的注释处理将不会起任何作用

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

另见:


spring+kotlin+AOP工作得很好,只需转到并生成一个具有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')
    ...
}
插件kotlin spring使所有类都打开以允许AOP

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

@Aspect
@Component
class MyAspect {
...
重要:使用@aspect@Component注释注释方面类


小菜一碟!:)

值得一提的是,我们在android项目中需要aspectJ编织,但我们真的想转移到kotlin,所以我们必须解决这个问题。因此,这个线程中使用spring或maven的解决方案对我们不起作用。这是android gradle项目的解决方案,但是,这将破坏增量编译,从而降低构建时间和/或最终破坏某些东西。在我重新思考我们的架构并逐步淘汰aspectJ或(希望)android开始支持它之前,这会一直持续下去

在OP的一些答案和注释中有一点混淆,即kapt解决了这个问题,但kapt允许您进行编译时注释处理,而不是编织。也就是说,注释处理器允许您基于注释生成代码,但不允许您将逻辑注入现有代码

这篇文章建立在将aspectJ添加到android的博客之上:

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

应用程序/build.gradle的顶部添加:

buildscript {
    ext.aspectjVersion = '1.9.1'
    dependencies {
        classpath "org.aspectj:aspectjtools:$aspectjVersion"
    }
}
在应用程序/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
            }
        }
    }
}
你可以用


所以我想我已经为Android找到了一个很好的(但冗长的)解决方案。在撰写本文时,我正在使用Gradle 6.7、Android插件4.1.0和AspectJ工具1.9.6

问题的要点是:

  • Java是通过task
    CompiledBugJavaWithJavaC
  • Kotlin由任务编译
    compiledBugKotlin
  • Gradle可以运行其中一个任务,也可以同时运行两个任务,也可以不运行任何任务
  • compileDebugJavaWithJavac
    取决于
    compileDebugKotlin
  • 编织Kotlin通常需要Java类
如果仔细观察这些要点,就会发现不能将编织作为编译Kotlin的一部分,因为此时可能缺少Java类。如果您这样做,您将收到以下警告:

警告:不正确的类路径:C:\Users\user\StudioProjects\myapp\app\build\intermediates\javac\debug\classes

以及错误,例如

错误:无法确定缺少类型myapp.Foo.Bar的修饰符

因此,更好的方法是在编译Java类之前推迟编织。但由于修改文件不是作为编译任务的一部分,因此会丢失增量构建。。。此外,这种延迟的编织非常难以正确执行记住,没有一个编译任务可能实际计划运行


真正的解决方案是将编织包装在一个框架中,这将产生一个带有自己输入和输出的渐变任务。这意味着您将不会污染编译任务的文件,可以说,这些任务以及此任务都是最新的。这需要相当多的代码,但它相当合理

首先,将其放入项目
build.gradle.kts

buildscript{
依赖关系{
类路径(“org.aspectj:aspectjtools:1.9.6”)
}
}
这是从构建脚本的“内部”运行编织所必需的。如果您想在单独的进程中运行编织,这在Windows上是一个好主意,那么您需要这个jar的路径,您可以通过将以下内容添加到您的应用程序
build.gradle.kts

val编织:按配置配置。创建
依赖关系{
编织(“org.aspectj:aspectjtools:1.9.6”)
}
最后,将AspectJ运行时放在类路径上(app
build.gradle.kts
,注意我只需要在调试构建中编织):

依赖项{
调试实现(“org.aspectj:aspectjrt:1.9.6”)
}
现在,这是我的设置。我有一个本地日志库,
:cats
,它包含我想要编织的方面。日志语句仅在我的项目中,而不在其他任何地方。另外,我只想在调试版本中运行这些。下面是将猫“编织”到应用程序中的转换(应用程序的
build.gradle.kts
):

class-TransformCats:Transform(){
重写fun getName():String=TransformCats::class.simpleName!!
重写fun getInputTypes()=集合(QualifiedContent.DefaultContentType.CLASSES)
//仅在应用程序类中查找注释
//转换将使用这些类并将编织类放入输出目录中
重写fun getScopes()=mutableSetOf(QualifiedContent.Scope.PROJECT)
//…但其他的都在我们班上
//这些将不会被转换所触及
重写fun getReferencedScopes()=可变集合(QualifiedContent.Scope.SUB_项目,
QualifiedContent.Scope.EXTERNAL_库)
override fun isIncremental()=false
//只在de上运行
buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "io.freefair.gradle:aspectj-plugin:5.2.1"
  }
}

apply plugin: "io.freefair.aspectj.post-compile-weaving"