Skip to content

Commit 1911ca7

Browse files
committed
Support invoking bridged suspending functions in AopUtils
Closes gh-33045
1 parent f4a73b7 commit 1911ca7

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,10 @@ public static Object invokeJoinpointUsingReflection(@Nullable Object target, Met
349349

350350
// Use reflection to invoke the method.
351351
try {
352-
ReflectionUtils.makeAccessible(method);
353-
return (coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(method) ?
354-
KotlinDelegate.invokeSuspendingFunction(method, target, args) : method.invoke(target, args));
352+
Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
353+
ReflectionUtils.makeAccessible(originalMethod);
354+
return (coroutinesReactorPresent && KotlinDetector.isSuspendingFunction(originalMethod) ?
355+
KotlinDelegate.invokeSuspendingFunction(originalMethod, target, args) : originalMethod.invoke(target, args));
355356
}
356357
catch (InvocationTargetException ex) {
357358
// Invoked method threw a checked exception.

spring-aop/src/test/kotlin/org/springframework/aop/support/AopUtilsKotlinTests.kt

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,19 +34,48 @@ class AopUtilsKotlinTests {
3434
@Test
3535
fun `Invoking suspending function should return Mono`() {
3636
val value = "foo"
37-
val method = ReflectionUtils.findMethod(AopUtilsKotlinTests::class.java, "suspendingFunction",
38-
String::class.java, Continuation::class.java)!!
37+
val method = ReflectionUtils.findMethod(WithoutInterface::class.java, "handle",
38+
String::class. java, Continuation::class.java)!!
3939
val continuation = Continuation<Any>(CoroutineName("test")) { }
40-
val result = AopUtils.invokeJoinpointUsingReflection(this, method, arrayOf(value, continuation))
40+
val result = AopUtils.invokeJoinpointUsingReflection(WithoutInterface(), method, arrayOf(value, continuation))
4141
assertThat(result).isInstanceOfSatisfying(Mono::class.java) {
4242
assertThat(it.block()).isEqualTo(value)
4343
}
4444
}
4545

46+
@Test
47+
fun `Invoking suspending function on bridged method should return Mono`() {
48+
val value = "foo"
49+
val bridgedMethod = ReflectionUtils.findMethod(WithInterface::class.java, "handle", Object::class.java, Continuation::class.java)!!
50+
val continuation = Continuation<Any>(CoroutineName("test")) { }
51+
val result = AopUtils.invokeJoinpointUsingReflection(WithInterface(), bridgedMethod, arrayOf(value, continuation))
52+
assertThat(result).isInstanceOfSatisfying(Mono::class.java) {
53+
assertThat(it.block()).isEqualTo(value)
54+
}
55+
}
56+
4657
@Suppress("unused")
4758
suspend fun suspendingFunction(value: String): String {
4859
delay(1)
4960
return value
5061
}
5162

63+
class WithoutInterface {
64+
suspend fun handle(value: String): String {
65+
delay(1)
66+
return value
67+
}
68+
}
69+
70+
interface ProxyInterface<T> {
71+
suspend fun handle(value: T): T
72+
}
73+
74+
class WithInterface : ProxyInterface<String> {
75+
override suspend fun handle(value: String): String {
76+
delay(1)
77+
return value
78+
}
79+
}
80+
5281
}

0 commit comments

Comments
 (0)