@@ -20,6 +20,9 @@ import kotlinx.coroutines.delay
20
20
import kotlinx.coroutines.runBlocking
21
21
import org.aopalliance.intercept.MethodInterceptor
22
22
import org.aopalliance.intercept.MethodInvocation
23
+ import org.aspectj.lang.ProceedingJoinPoint
24
+ import org.aspectj.lang.annotation.Around
25
+ import org.aspectj.lang.annotation.Aspect
23
26
import org.assertj.core.api.Assertions.assertThat
24
27
import org.junit.jupiter.api.Test
25
28
import org.springframework.aop.framework.autoproxy.AspectJAutoProxyInterceptorKotlinIntegrationTests.InterceptorConfig
@@ -28,10 +31,18 @@ import org.springframework.beans.factory.annotation.Autowired
28
31
import org.springframework.context.annotation.Bean
29
32
import org.springframework.context.annotation.Configuration
30
33
import org.springframework.context.annotation.EnableAspectJAutoProxy
34
+ import org.springframework.stereotype.Component
31
35
import org.springframework.test.annotation.DirtiesContext
32
36
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig
37
+ import org.springframework.transaction.annotation.EnableTransactionManagement
38
+ import org.springframework.transaction.annotation.Transactional
39
+ import org.springframework.transaction.testfixture.ReactiveCallCountingTransactionManager
33
40
import reactor.core.publisher.Mono
34
41
import java.lang.reflect.Method
42
+ import kotlin.annotation.AnnotationTarget.ANNOTATION_CLASS
43
+ import kotlin.annotation.AnnotationTarget.CLASS
44
+ import kotlin.annotation.AnnotationTarget.FUNCTION
45
+ import kotlin.annotation.AnnotationTarget.TYPE
35
46
36
47
37
48
/* *
@@ -43,7 +54,9 @@ import java.lang.reflect.Method
43
54
class AspectJAutoProxyInterceptorKotlinIntegrationTests (
44
55
@Autowired val echo : Echo ,
45
56
@Autowired val firstAdvisor : TestPointcutAdvisor ,
46
- @Autowired val secondAdvisor : TestPointcutAdvisor ) {
57
+ @Autowired val secondAdvisor : TestPointcutAdvisor ,
58
+ @Autowired val countingAspect : CountingAspect ,
59
+ @Autowired val reactiveTransactionManager : ReactiveCallCountingTransactionManager ) {
47
60
48
61
@Test
49
62
fun `Multiple interceptors with regular function` () {
@@ -67,8 +80,22 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
67
80
assertThat(secondAdvisor.interceptor.invocations).singleElement().matches { Mono ::class .java.isAssignableFrom(it) }
68
81
}
69
82
83
+ @Test // gh-33095
84
+ fun `Aspect and reactive transactional with suspending function` () {
85
+ assertThat(countingAspect.counter).isZero()
86
+ assertThat(reactiveTransactionManager.commits).isZero()
87
+ val value = " Hello!"
88
+ runBlocking {
89
+ assertThat(echo.suspendingTransactionalEcho(value)).isEqualTo(value)
90
+ }
91
+ assertThat(countingAspect.counter).`as `(" aspect applied" ).isOne()
92
+ assertThat(reactiveTransactionManager.begun).isOne()
93
+ assertThat(reactiveTransactionManager.commits).`as `(" transactional applied" ).isOne()
94
+ }
95
+
70
96
@Configuration
71
97
@EnableAspectJAutoProxy
98
+ @EnableTransactionManagement
72
99
open class InterceptorConfig {
73
100
74
101
@Bean
@@ -77,6 +104,13 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
77
104
@Bean
78
105
open fun secondAdvisor () = TestPointcutAdvisor ().apply { order = 1 }
79
106
107
+ @Bean
108
+ open fun countingAspect () = CountingAspect ()
109
+
110
+ @Bean
111
+ open fun transactionManager (): ReactiveCallCountingTransactionManager {
112
+ return ReactiveCallCountingTransactionManager ()
113
+ }
80
114
81
115
@Bean
82
116
open fun echo (): Echo {
@@ -107,6 +141,24 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
107
141
}
108
142
}
109
143
144
+ @Target(CLASS , FUNCTION , ANNOTATION_CLASS , TYPE )
145
+ @Retention(AnnotationRetention .RUNTIME )
146
+ annotation class Counting ()
147
+
148
+ @Aspect
149
+ @Component
150
+ class CountingAspect {
151
+
152
+ var counter: Long = 0
153
+
154
+ @Around(" @annotation(org.springframework.aop.framework.autoproxy.AspectJAutoProxyInterceptorKotlinIntegrationTests.Counting)" )
155
+ fun logging (joinPoint : ProceedingJoinPoint ): Any {
156
+ return (joinPoint.proceed(joinPoint.args) as Mono <* >).doOnTerminate {
157
+ counter++
158
+ }
159
+ }
160
+ }
161
+
110
162
open class Echo {
111
163
112
164
open fun echo (value : String ): String {
@@ -118,6 +170,13 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
118
170
return value
119
171
}
120
172
173
+ @Transactional
174
+ @Counting
175
+ open suspend fun suspendingTransactionalEcho (value : String ): String {
176
+ delay(1 )
177
+ return value
178
+ }
179
+
121
180
}
122
181
123
182
}
0 commit comments