From 69cb68f7d64ddce60b9653a01a7c3b66e5d9f413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Mon, 17 Oct 2022 12:26:45 +0200 Subject: [PATCH] Add Kotlin data class components support to BindingReflectionHintsRegistrar Closes gh-29316 --- .../hint/BindingReflectionHintsRegistrar.java | 21 +++++++++++++++++++ ...linBindingReflectionHintsRegistrarTests.kt | 13 +++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java b/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java index d56189935ac..1b02a05af2d 100644 --- a/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java +++ b/spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java @@ -22,6 +22,8 @@ import java.lang.reflect.Type; import java.util.LinkedHashSet; import java.util.Set; +import kotlin.jvm.JvmClassMappingKt; +import kotlin.reflect.KClass; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -101,6 +103,7 @@ public class BindingReflectionHintsRegistrar { } } if (KotlinDetector.isKotlinType(clazz)) { + KotlinDelegate.registerComponentHints(hints, clazz); registerKotlinSerializationHints(hints, clazz); } }); @@ -148,4 +151,22 @@ public class BindingReflectionHintsRegistrar { } } + /** + * Inner class to avoid a hard dependency on Kotlin at runtime. + */ + private static class KotlinDelegate { + + public static void registerComponentHints(ReflectionHints hints, Class type) { + KClass kClass = JvmClassMappingKt.getKotlinClass(type); + if (kClass.isData()) { + for (Method method : type.getMethods()) { + String methodName = method.getName(); + if (methodName.startsWith("component") || methodName.equals("copy")) { + hints.registerMethod(method, ExecutableMode.INVOKE); + } + } + } + } + } + } diff --git a/spring-core/src/test/kotlin/org/springframework/aot/hint/KotlinBindingReflectionHintsRegistrarTests.kt b/spring-core/src/test/kotlin/org/springframework/aot/hint/KotlinBindingReflectionHintsRegistrarTests.kt index 67819bac415..cc00a89d354 100644 --- a/spring-core/src/test/kotlin/org/springframework/aot/hint/KotlinBindingReflectionHintsRegistrarTests.kt +++ b/spring-core/src/test/kotlin/org/springframework/aot/hint/KotlinBindingReflectionHintsRegistrarTests.kt @@ -19,6 +19,7 @@ package org.springframework.aot.hint import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.ThrowingConsumer import org.junit.jupiter.api.Test +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates /** * Tests for Kotlin support in [BindingReflectionHintsRegistrar]. @@ -32,7 +33,7 @@ class KotlinBindingReflectionHintsRegistrarTests { private val hints = RuntimeHints() @Test - fun `Register type for Kotlinx serialization`() { + fun `Register reflection hints for Kotlinx serialization`() { bindingRegistrar.registerReflectionHints(hints.reflection(), SampleSerializableClass::class.java) assertThat(hints.reflection().typeHints()).satisfiesExactlyInAnyOrder( ThrowingConsumer { typeHint: TypeHint -> @@ -59,7 +60,17 @@ class KotlinBindingReflectionHintsRegistrarTests { }) }) } + + @Test + fun `Register reflection hints for Kotlin data class`() { + bindingRegistrar.registerReflectionHints(hints.reflection(), SampleDataClass::class.java) + assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "component1")).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "copy")).accepts(hints) + assertThat(RuntimeHintsPredicates.reflection().onMethod(SampleDataClass::class.java, "getName")).accepts(hints) + } } @kotlinx.serialization.Serializable class SampleSerializableClass(val name: String) + +data class SampleDataClass(val name: String)