Spring AOPのAdviceでsuspend関数を実行する

2023/12/23に公開

Spring Framework 6.1 (Spring Boot 3.2)より前

@Component
@Aspect
class MyAspect {
    @Around("xxx")
    fun execute(joinPoint: ProceedingJoinPoint): Any? {
        val originalContinuation = joinPoint.args.last() as Continuation<Any>
        val argsOtherThanContinuation = joinPoint.args.sliceArray(0..<joinPoint.args.size - 1)
        return suspend {
            callSuspendFunction()
            suspendCoroutineUninterceptedOrReturn<Any> { continuation ->
                joinPoint.proceed(argsOtherThanContinuation + continuation)
            }
        }.startCoroutineUninterceptedOrReturn(originalContinuation)
    }
}

Spring Framework 6.1 (Spring Boot 3.2)以降

@Component
@Aspect
class MyAspect {
    @Around("xxx")
    fun execute(joinPoint: ProceedingJoinPoint): Any? = mono {
        callSuspendFunction()
    }.then(joinPoint.proceed() as Mono<*>)
}

Discussion