Spring AOP (AspectJ) with Kotlin 和 Gradle - 我无法让它工作



我有一个Spring Boot+Kotlin+Gradle项目。我想为我的用例创建一个小库。这个库应该使用AOP来消除我观察到的一些交叉问题。

因此,我开始将这两个依赖项添加到我的gradle构建文件中。

build.gradle.kts

implementation("org.springframework:spring-aop:5.2.9.RELEASE")
implementation("org.springframework:spring-aspects:5.2.9.RELEASE")

由于interwebs的一些建议,我还添加了freefair aspectj插件。根据本文档,我创建的以下方面应放在src/main/aspectj中:https://docs.freefair.io/gradle-plugins/5.2.1/reference/#_io_freefair_aspectj

这个插件通过向每个源集添加一个AspectJ目录,为项目添加了对AspectJ的支持。src/main/aspectj目录中包含的源代码将由compileAspectj任务使用ajc编译。

plugins {
// ...
id("io.freefair.aspectj") version "5.2.1"
// ...
}

然后,我开始创建我的第一个方面,它与用@Foozy注释的每个方法相匹配

src/main/aspectj/FoozyAspect.kt<"特殊"源路径

@Component
@Aspect
class FoozyAspect {
@Before("@annotation(com.client.annotation.Foozy)")
fun doStuff() {
LOG.info("Do Stuff")
}
companion object {
private val LOG = LoggerFactory.getLogger(FoozyAspect::class.java)
}
}

然后我创建了这个注释

src/main/kotlin/com.client.annotation/Foozy.kt

@Target(AnnotationTarget.FUNCTION)
annotation class Foozy

现在,为了测试是否一切如预期,我创建了一个单元测试

src/test/kotlin/FoozyAspectTest.kt

@SpringBootTest
@EnableAspectJAutoProxy
internal class FoozyAspectTest {
private val testCandidate: TestCandidate = TestCandidate()
@Test
fun `should work with aspect`() {
testCandidate.doStuff()
}
}

src/test/TestCandidate.kt

class TestCandidate {
@Foozy
fun doStuff(): String {
return "stuff"
}
}

结果

在调试模式下执行文本不会产生等待的信息日志Do Stuff,也不会在FoozyAspect.ktdoStuff((方法中的断点处停止线程。我不知道在这里配置什么。出于充分的理由,我有点怀疑我把不同的";"方式";为了让它发挥作用,或者我只是错过了预配置/先决条件中的一些最后步骤。

AspectJ编译器无法编译Kotlin源代码。src/main/aspectj中的.kt文件将被完全忽略。

根据你真正想做的事情,你有不同的选择:

你是想让你的方面在编译时由ajc编织,还是只想使用"普通的";Spring AOP?

不同之处如下:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-选择

如果你只想使用SpringAOP,你不需要一个特殊的gradle插件。只需将.kt文件放在src/main/kotlin中,然后按照SpringAOP文档进行操作。

如果你想在编译时用ajc编织你的方面,你有两个选择:

  1. 保留io.freefair.aspectj插件来编译并一步编织方面:将你的方面实现为.java.aj,这样它就可以由ajc编译
  2. 切换到io.freefair.aspectj.post-compile-weaving插件以分离编译和编织步骤:在这种情况下,您可以将Aspect实现保留为Kotlin,但必须将其放在src/main/kotlin中。然后你的方面将由kotlinc编译,然后由ajc编织

这看起来像是经典Spring AOP问题的第347个副本:如果您阅读手册,您会注意到Spring AOP只适用于Spring组件,例如通过@Component@Bean声明的。

您的TestCandidate似乎是一个POJO,所以Spring对此一无所知。此外,如果您将其作为一个组件,请确保从容器中获得一个实例,而不是仅通过测试中的构造函数调用创建一个实例。

最新更新