与Kotlin的AOP

我用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需要摆脱最后(即在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 } 

该方法的LoC复杂性是O(N * K),其中N是一些方法,K是我想要应用的许多方面。

所以我所看到的是在Kotlin方面可能有效的(在性能和LoC方面)解决方案,而不使用cglib生成的代理,因为它们施加了太多的限制,比如告别final class,没有无参数的public构造函数。

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