Skip to content

Commit 50906e7

Browse files
committed
Merge branch '6.1.x'
2 parents 681cfce + 6becfe2 commit 50906e7

File tree

2 files changed

+36
-23
lines changed

2 files changed

+36
-23
lines changed

integration-tests/src/test/kotlin/org/springframework/aop/framework/autoproxy/AspectJAutoProxyInterceptorKotlinIntegrationTests.kt

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import org.junit.jupiter.api.Test
2828
import org.springframework.aop.framework.autoproxy.AspectJAutoProxyInterceptorKotlinIntegrationTests.InterceptorConfig
2929
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor
3030
import org.springframework.beans.factory.annotation.Autowired
31+
import org.springframework.cache.CacheManager
32+
import org.springframework.cache.annotation.Cacheable
33+
import org.springframework.cache.annotation.EnableCaching
34+
import org.springframework.cache.concurrent.ConcurrentMapCacheManager
3135
import org.springframework.context.annotation.Bean
3236
import org.springframework.context.annotation.Configuration
3337
import org.springframework.context.annotation.EnableAspectJAutoProxy
@@ -93,9 +97,26 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
9397
assertThat(reactiveTransactionManager.commits).`as`("transactional applied").isOne()
9498
}
9599

100+
@Test // gh-33210
101+
fun `Aspect and cacheable with suspending function`() {
102+
assertThat(countingAspect.counter).isZero()
103+
val value = "Hello!"
104+
runBlocking {
105+
assertThat(echo.suspendingCacheableEcho(value)).isEqualTo("$value 0")
106+
assertThat(echo.suspendingCacheableEcho(value)).isEqualTo("$value 0")
107+
assertThat(echo.suspendingCacheableEcho(value)).isEqualTo("$value 0")
108+
assertThat(countingAspect.counter).`as`("aspect applied once").isOne()
109+
110+
assertThat(echo.suspendingCacheableEcho("$value bis")).isEqualTo("$value bis 1")
111+
assertThat(echo.suspendingCacheableEcho("$value bis")).isEqualTo("$value bis 1")
112+
}
113+
assertThat(countingAspect.counter).`as`("aspect applied once per key").isEqualTo(2)
114+
}
115+
96116
@Configuration
97117
@EnableAspectJAutoProxy
98118
@EnableTransactionManagement
119+
@EnableCaching
99120
open class InterceptorConfig {
100121

101122
@Bean
@@ -112,6 +133,11 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
112133
return ReactiveCallCountingTransactionManager()
113134
}
114135

136+
@Bean
137+
open fun cacheManager(): CacheManager {
138+
return ConcurrentMapCacheManager()
139+
}
140+
115141
@Bean
116142
open fun echo(): Echo {
117143
return Echo()
@@ -155,7 +181,7 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
155181
fun logging(joinPoint: ProceedingJoinPoint): Any {
156182
return (joinPoint.proceed(joinPoint.args) as Mono<*>).doOnTerminate {
157183
counter++
158-
}
184+
}.checkpoint("CountingAspect")
159185
}
160186
}
161187

@@ -177,6 +203,15 @@ class AspectJAutoProxyInterceptorKotlinIntegrationTests(
177203
return value
178204
}
179205

206+
open var cacheCounter: Int = 0
207+
208+
@Counting
209+
@Cacheable("something")
210+
open suspend fun suspendingCacheableEcho(value: String): String {
211+
delay(1)
212+
return "$value ${cacheCounter++}"
213+
}
214+
180215
}
181216

182217
}

spring-context/src/main/java/org/springframework/cache/interceptor/CacheInterceptor.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,9 @@
1919
import java.io.Serializable;
2020
import java.lang.reflect.Method;
2121

22-
import kotlin.coroutines.Continuation;
23-
import kotlin.coroutines.CoroutineContext;
24-
import kotlinx.coroutines.Job;
2522
import org.aopalliance.intercept.MethodInterceptor;
2623
import org.aopalliance.intercept.MethodInvocation;
27-
import org.reactivestreams.Publisher;
2824

29-
import org.springframework.core.CoroutinesUtils;
30-
import org.springframework.core.KotlinDetector;
3125
import org.springframework.lang.Nullable;
3226
import org.springframework.util.Assert;
3327

@@ -58,9 +52,6 @@ public Object invoke(final MethodInvocation invocation) throws Throwable {
5852

5953
CacheOperationInvoker aopAllianceInvoker = () -> {
6054
try {
61-
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isSuspendingFunction(method)) {
62-
return KotlinDelegate.invokeSuspendingFunction(method, invocation.getThis(), invocation.getArguments());
63-
}
6455
return invocation.proceed();
6556
}
6657
catch (Throwable ex) {
@@ -78,17 +69,4 @@ public Object invoke(final MethodInvocation invocation) throws Throwable {
7869
}
7970
}
8071

81-
82-
/**
83-
* Inner class to avoid a hard dependency on Kotlin at runtime.
84-
*/
85-
private static class KotlinDelegate {
86-
87-
public static Publisher<?> invokeSuspendingFunction(Method method, @Nullable Object target, Object... args) {
88-
Continuation<?> continuation = (Continuation<?>) args[args.length - 1];
89-
CoroutineContext coroutineContext = continuation.getContext().minusKey(Job.Key);
90-
return CoroutinesUtils.invokeSuspendingFunction(coroutineContext, method, target, args);
91-
}
92-
}
93-
9472
}

0 commit comments

Comments
 (0)