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.This looks like the 347th duplicate of a classical Spring AOP question: If you read the manual, you will notice that Spring AOP only works for Spring components, e.g. declared via @Component
or @Bean
.
Your TestCandidate
seems to be a POJO, so Spring does not know about it. Also if you make it a component, make sure you get an instance from the container and do not just create one via constructor call in your test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With