当前位置: 首页 > 知识库问答 >
问题:

带Kotlin的AOP

祝高超
2023-03-14

我在Java中经常使用AOP。看起来传统的java方法很容易在Kotlin中重用。鉴于Kotlin强调不变性,JDK代理似乎是Kotlin中最可行的解决方案,前提是您遵循相同的接口优先(在Kotlin中更好地说是特征优先)编程风格,例如:

trait MyService {
 fun add(a: Int, b: Int): Int
}

class MyServiceImpl: MyService {...}

因此,现在可以很容易地用Spring/AOP编写一个方面,并将其应用到MyServiceImpl实例中。应该提到的是,基于Java接口生成的代理可能更受Kotlin开发人员的青睐,因为cglib要求摆脱final(即在Kotlin中求助于开放类),并对每个应该由AOP代理包装的类使用无参数公共构造函数。

同时,不幸的是,基于Java接口生成的代理会带来很大的性能损失,所以我想知道在某些情况下,AOP编程是否可以更直观地进行,或者是对Kotlin更原生地进行。

因此,考虑下面的示例,当我想将AOP用于:

  • 记录从服务公开的每个方法的参数和返回结果。
  • 在函数调用之前启动事务,并在函数调用完成后关闭事务(提交/回滚取决于在进行特定服务调用时是否引发异常)。

在前面提到的MyService/MyServiceImpl示例中,最有效但不幸的是最冗长的强力解决方案可能如下所示:

class MyServiceLoggingWrapper(val delegate: MyService): MyService {
  val logger = LoggerFactory.getLogger(this.javaClass)

  override fun add(a: Int, b: Int): Int {
    val result = delegate.add(a, b);
    logger.info("MyService.add({}, {}) = {}", a, b, result);
    return result;
  }
} 

class MyServiceTxWrapper(val delegate: MyService, val txManager: TransactionManager): MyService {
 // similar lengthy implementation
}

该方法锁定复杂度为O(N*K),其中N是许多方法,K是我想应用的许多方面。

因此,我所寻找的是一个可能有效的解决方案(在性能和LoC方面都是如此),Kotlin中的方面最好不要求助于CGLIB生成的代理,因为它们施加了太多的限制,比如告别final类和没有无参数的公共构造函数。

共有1个答案

叶琦
2023-03-14

我不是Kotlin用户,但考虑到它的目标是JVM,我建议尝试完全成熟的AspectJ,而不是基于代理的“AOP Lite”方法,比如Spring AOP。AspectJ不需要/使用动态代理,它在编译期间或编译之后(二进制编织)甚至在类加载期间(加载时编织)生成字节代码。

 类似资料:
  • 在一个同时使用静态编程语言和java的Android项目中,我想在一些java文件中使用静态编程语言函数和。 所以我想到了使用扩展。我做了下面的工作, 然而,我曾考虑将分隔符作为参数传递,但在java中尝试使用“删除第二个参数…”时,它给了我一个错误 方法正确吗?能做到吗?

  • 我正试图将一个Android应用程序从Java转换为Kotlin。应用程序中有几个单人。我为没有构造函数参数的单例使用了一个伴生对象。还有另一个接受构造函数参数的单例。 Java代码:

  • 我在这种情况下有点麻烦 问题是,如果"b"为空,运行块将被执行,即使elvis操作符引用了"a"let。我已经试过用"应用"代替"运行",同样的事情发生了

  • 基于此链接中的答案,创建了一个包含测试类的测试套件 返回错误 但是每个添加的测试类都有测试方法,并且单独运行

  • 在2.1版本中,Room增加了对协同程序的支持,但我无法让它工作。这应该和添加依赖项一样简单,但不知为什么我忽略了一些东西。 在我的build.gradle我有协程的依赖关系,房间和房间协程 我已经尝试重新同步gradle,清理和重建项目。 在我的Doa中,我有如下方法 当试图构建项目时,Room不知道如何处理挂起的功能,会发生以下错误: 我真的不知道我错过了什么,自从新的房间版本以来,我找不到有

  • 在最近的一个项目中,我已经将一个java文件转换为kotlin文件,问题是我在下面的代码中遇到了一个错误: 原始java代码片段: