我有一个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.kt
doStuff((方法中的断点处停止线程。我不知道在这里配置什么。出于充分的理由,我有点怀疑我把不同的";"方式";为了让它发挥作用,或者我只是错过了预配置/先决条件中的一些最后步骤。
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编织你的方面,你有两个选择:
- 保留
io.freefair.aspectj
插件来编译并一步编织方面:将你的方面实现为.java
或.aj
,这样它就可以由ajc编译 - 切换到
io.freefair.aspectj.post-compile-weaving
插件以分离编译和编织步骤:在这种情况下,您可以将Aspect实现保留为Kotlin,但必须将其放在src/main/kotlin
中。然后你的方面将由kotlinc编译,然后由ajc编织
这看起来像是经典Spring AOP问题的第347个副本:如果您阅读手册,您会注意到Spring AOP只适用于Spring组件,例如通过@Component
或@Bean
声明的。
您的TestCandidate
似乎是一个POJO,所以Spring对此一无所知。此外,如果您将其作为一个组件,请确保从容器中获得一个实例,而不是仅通过测试中的构造函数调用创建一个实例。