Skip to content

Instantly share code, notes, and snippets.

@pjanczyk
Last active August 30, 2023 10:25
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pjanczyk/5d958821bafd911a5996bc0b66788ea3 to your computer and use it in GitHub Desktop.
Save pjanczyk/5d958821bafd911a5996bc0b66788ea3 to your computer and use it in GitHub Desktop.
AOP w połączeniu z Kotlin Coroutines | https://vived.io/aop-w-polaczeniu-z-kotlin-coroutines/
package com.example
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.aspectj.lang.JoinPoint
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.AfterReturning
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.slf4j.LoggerFactory.getLogger
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
@Component
class Runner(
val foo: Foo,
val reactiveFoo: ReactiveFoo,
val coroutineFoo: CoroutineFoo,
) : CommandLineRunner {
override fun run(vararg args: String?) {
foo.add(2, 3)
reactiveFoo.add(2, 3).block()
runBlocking {
coroutineFoo.add(2, 3)
}
}
}
annotation class Logging
annotation class ReactiveLogging
annotation class CoroutineLogging
@Component
class Foo {
@Logging
fun add(a: Int, b: Int): Int = a + b
}
@Component
@Aspect
class LoggingAspect {
private val logger = getLogger(LoggingAspect::class.java)
@AfterReturning(
pointcut = "@annotation(Logging)",
returning = "result"
)
fun logResult(joinPoint: JoinPoint, result: Any?) {
logger.info("`${joinPoint.signature}` returned `${result}`")
}
}
@Component
class ReactiveFoo {
@ReactiveLogging
fun add(a: Int, b: Int): Mono<Int> = Mono.just(a + b)
}
@Component
@Aspect
class ReactiveLoggingAspect {
private val logger = getLogger(ReactiveLoggingAspect::class.java)
@Around(
"""
@annotation(ReactiveLogging) &&
execution(reactor.core.publisher.Mono *(..))
"""
)
fun logResult(joinPoint: ProceedingJoinPoint): Mono<Any> =
(joinPoint.proceed() as Mono<Any>)
.doOnNext { result ->
logger.info("`${joinPoint.signature}` returned `${result}`")
}
}
@Component
class CoroutineFoo {
@CoroutineLogging
suspend fun add(a: Int, b: Int): Int {
delay(100)
return a + b
}
}
val ProceedingJoinPoint.coroutineContinuation: Continuation<Any?>
get() = this.args.last() as Continuation<Any?>
val ProceedingJoinPoint.coroutineArgs: Array<Any?>
get() = this.args.sliceArray(0 until this.args.size - 1)
suspend fun ProceedingJoinPoint.proceedCoroutine(
args: Array<Any?> = this.coroutineArgs
): Any? =
suspendCoroutineUninterceptedOrReturn { continuation ->
this.proceed(args + continuation)
}
fun ProceedingJoinPoint.runCoroutine(
block: suspend () -> Any?
): Any? =
block.startCoroutineUninterceptedOrReturn(this.coroutineContinuation)
@Component
@Aspect
class CoroutineLoggingAspect {
private val logger = getLogger(CoroutineLoggingAspect::class.java)
@Around(
"""
@annotation(CoroutineLogging) &&
args(.., kotlin.coroutines.Continuation)
"""
)
fun logResult(joinPoint: ProceedingJoinPoint): Any? =
joinPoint.runCoroutine {
val result = joinPoint.proceedCoroutine()
logger.info("`${joinPoint.signature}` returned `${result}`")
result
}
}
plugins {
id("org.springframework.boot") version "2.5.3"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.21"
kotlin("plugin.spring") version "1.5.21"
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-aop")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
}
@und3rs
Copy link

und3rs commented Mar 28, 2023

Thank you so much!!
It works for me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment