I have a Spring Boot + Kotlin + Gradle project. I'd like to create a small library for my use-cases. This library should use AOP to remove some cross cutting concerns I observed.
Therefore I started adding these two dependencies to my gradle build file.
build.gradle.kts
implementation("org.springframework:spring-aop:5.2.9.RELEASE")
implementation("org.springframework:spring-aspects:5.2.9.RELEASE")
I also added the freefair aspectj plugin due some suggestions from the interwebs.
The following aspect I created should be placed in src/main/aspectj
according to this documentation: https://docs.freefair.io/gradle-plugins/5.2.1/reference/#_io_freefair_aspectj
This plugin adds AspectJ support to the project, by adding a aspectj directory to every source set. Source contained in the src/main/aspectj directory will be compiled with ajc by the compileAspectj task.
plugins {
// ...
id("io.freefair.aspectj") version "5.2.1"
// ...
}
I then started to create my first aspect that matches on every method which is annotated with @Foozy
src/main/aspectj/FoozyAspect.kt
< the 'special' source path
@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)
}
}
Then I created this annotation
src/main/kotlin/com.client.annotation/Foozy.kt
@Target(AnnotationTarget.FUNCTION)
annotation class Foozy
Now to test if everything works as expected I created a unit test
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"
}
}
Executing the text in debug mode does not yield the awaited info log Do Stuff
and also does not cease the thread at the breakpoint in the FoozyAspect.kt
doStuff() method.
I have no idea what to configure here.
For good reason I kinda have the suspicion that I am mixing up different "ways" to get this to work or am just missing some final steps in preconfiguration/prerequisites.
The AspectJ compiler can't compile Kotlin source code. Your .kt
file in src/main/aspectj
will be completely ignored.
You have different options depending on what you really want to do:
Do you want your Aspect to be woven by ajc at compile-time, or do you just want to use "plain" Spring AOP?
The differences are explained here: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-choosing
If you just want to use Spring AOP, you dont need a special gradle plugin. Just put your .kt
file in src/main/kotlin
and follow the Spring AOP docs.
If you want to weave your aspect at compile-time with ajc, you have two options:
io.freefair.aspectj
plugin to compile an weave the aspect in one step: Implement your aspect as .java
or .aj
so it can be compiled by ajcio.freefair.aspectj.post-compile-weaving
plugin in order to separate the compilation an weaving steps: In this case you can keep your Aspect implementation as Kotlin, but you have to put it in src/main/kotlin
. Your Aspect will then be compiled by kotlinc and then woven by ajc.