diff --git a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java
index 73e358c0d7..cfd19018f7 100644
--- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java
+++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java
@@ -332,9 +332,12 @@ public abstract class BeanUtils {
}
/**
- * Return the primary constructor of the provided class (single or default constructor
- * for Java classes and primary constructor for Kotlin classes), if any.
- * @param clazz the {@link Class} of the Kotlin class
+ * Return the primary constructor of the provided class. For Java classes, it returns
+ * the single or the default constructor if any. For Kotlin classes, it returns the Java
+ * constructor corresponding to the Kotlin primary constructor (as defined in
+ * Kotlin specification), the single or the default constructor if any.
+ *
+ * @param clazz the class to check
* @since 5.0
* @see Kotlin docs
*/
@@ -343,20 +346,21 @@ public abstract class BeanUtils {
public static Constructor findPrimaryConstructor(Class clazz) {
Assert.notNull(clazz, "Class must not be null");
if (useKotlinSupport(clazz)) {
- return KotlinDelegate.findPrimaryConstructor(clazz);
+ Constructor kotlinPrimaryConstructor = KotlinDelegate.findPrimaryConstructor(clazz);
+ if (kotlinPrimaryConstructor != null) {
+ return kotlinPrimaryConstructor;
+ }
+ }
+ Constructor[] ctors = (Constructor[]) clazz.getConstructors();
+ if (ctors.length == 1) {
+ return ctors[0];
}
else {
- Constructor[] ctors = (Constructor[]) clazz.getConstructors();
- if (ctors.length == 1) {
- return ctors[0];
+ try {
+ return clazz.getDeclaredConstructor();
}
- else {
- try {
- return clazz.getDeclaredConstructor();
- }
- catch (NoSuchMethodException ex) {
- return null;
- }
+ catch (NoSuchMethodException ex) {
+ return null;
}
}
}
diff --git a/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt b/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt
index 0cfa1db216..dd19bce123 100644
--- a/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt
+++ b/spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt
@@ -24,6 +24,7 @@ import org.junit.Test
*
* @author Sebastien Deleuze
*/
+@Suppress("unused", "UNUSED_PARAMETER")
class BeanUtilsKotlinTests {
@Test
@@ -65,10 +66,54 @@ class BeanUtilsKotlinTests {
assertEquals(12, baz.param2)
}
+ @Test
+ fun `2 constructors with default one`() {
+ assertEquals(TwoConstructorsWithDefaultOne::class.java.getDeclaredConstructor(), BeanUtils.findPrimaryConstructor(TwoConstructorsWithDefaultOne::class.java))
+ }
+
+ @Test
+ fun `2 constructors without default one`() {
+ assertNull(BeanUtils.findPrimaryConstructor(TwoConstructorsWithoutDefaultOne::class.java))
+ }
+
+ @Test
+ fun `1 constructor with default one`() {
+ assertEquals(OneConstructorWithDefaultOne::class.java.getDeclaredConstructor(), BeanUtils.findPrimaryConstructor(OneConstructorWithDefaultOne::class.java))
+ }
+
+ @Test
+ fun `1 constructor without default one`() {
+ assertEquals(OneConstructorWithoutDefaultOne::class.java.getDeclaredConstructor(String::class.java), BeanUtils.findPrimaryConstructor(OneConstructorWithoutDefaultOne::class.java))
+ }
+
class Foo(val param1: String, val param2: Int)
class Bar(val param1: String, val param2: Int = 12)
class Baz(var param1: String = "a", var param2: Int = 12)
+ class TwoConstructorsWithDefaultOne {
+
+ constructor()
+
+ constructor(param1: String)
+ }
+
+ class TwoConstructorsWithoutDefaultOne {
+
+ constructor(param1: String)
+
+ constructor(param1: String, param2: String)
+ }
+
+ class OneConstructorWithDefaultOne {
+
+ constructor()
+ }
+
+ class OneConstructorWithoutDefaultOne {
+
+ constructor(param1: String)
+ }
+
}