Skip to content

Commit a638828

Browse files
committed
Merge branch '6.2.x'
2 parents 106e5c7 + 67ed64a commit a638828

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

spring-beans/src/main/java/org/springframework/beans/BeanUtils.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.Set;
3434

3535
import kotlin.jvm.JvmClassMappingKt;
36+
import kotlin.jvm.internal.DefaultConstructorMarker;
3637
import kotlin.reflect.KClass;
3738
import kotlin.reflect.KFunction;
3839
import kotlin.reflect.KParameter;
@@ -659,7 +660,9 @@ public static MethodParameter getWriteMethodParameter(PropertyDescriptor pd) {
659660
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
660661
@Nullable String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
661662
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
662-
Assert.state(paramNames.length == ctor.getParameterCount(),
663+
int parameterCount = (KotlinDetector.isKotlinReflectPresent() && KotlinDelegate.hasDefaultConstructorMarker(ctor) ?
664+
ctor.getParameterCount() - 1 : ctor.getParameterCount());
665+
Assert.state(paramNames.length == parameterCount,
663666
() -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor);
664667
return paramNames;
665668
}
@@ -928,6 +931,11 @@ public static <T> T instantiateClass(Constructor<T> ctor, @Nullable Object... ar
928931
}
929932
return kotlinConstructor.callBy(argParameters);
930933
}
934+
935+
public static boolean hasDefaultConstructorMarker(Constructor<?> ctor) {
936+
int parameterCount = ctor.getParameterCount();
937+
return parameterCount > 0 && ctor.getParameters()[parameterCount -1].getType() == DefaultConstructorMarker.class;
938+
}
931939
}
932940

933941
}

spring-beans/src/test/kotlin/org/springframework/beans/BeanUtilsKotlinTests.kt

Lines changed: 45 additions & 8 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-2025 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.
@@ -93,7 +93,6 @@ class BeanUtilsKotlinTests {
9393
@Test
9494
fun `Instantiate value class`() {
9595
val constructor = BeanUtils.findPrimaryConstructor(ValueClass::class.java)!!
96-
assertThat(constructor).isNotNull()
9796
val value = "Hello value class!"
9897
val instance = BeanUtils.instantiateClass(constructor, value)
9998
assertThat(instance).isEqualTo(ValueClass(value))
@@ -102,7 +101,6 @@ class BeanUtilsKotlinTests {
102101
@Test
103102
fun `Instantiate value class with multiple constructors`() {
104103
val constructor = BeanUtils.findPrimaryConstructor(ValueClassWithMultipleConstructors::class.java)!!
105-
assertThat(constructor).isNotNull()
106104
val value = "Hello value class!"
107105
val instance = BeanUtils.instantiateClass(constructor, value)
108106
assertThat(instance).isEqualTo(ValueClassWithMultipleConstructors(value))
@@ -111,7 +109,6 @@ class BeanUtilsKotlinTests {
111109
@Test
112110
fun `Instantiate class with value class parameter`() {
113111
val constructor = BeanUtils.findPrimaryConstructor(ConstructorWithValueClass::class.java)!!
114-
assertThat(constructor).isNotNull()
115112
val value = ValueClass("Hello value class!")
116113
val instance = BeanUtils.instantiateClass(constructor, value)
117114
assertThat(instance).isEqualTo(ConstructorWithValueClass(value))
@@ -120,7 +117,6 @@ class BeanUtilsKotlinTests {
120117
@Test
121118
fun `Instantiate class with nullable value class parameter`() {
122119
val constructor = BeanUtils.findPrimaryConstructor(ConstructorWithNullableValueClass::class.java)!!
123-
assertThat(constructor).isNotNull()
124120
val value = ValueClass("Hello value class!")
125121
var instance = BeanUtils.instantiateClass(constructor, value)
126122
assertThat(instance).isEqualTo(ConstructorWithNullableValueClass(value))
@@ -131,7 +127,6 @@ class BeanUtilsKotlinTests {
131127
@Test
132128
fun `Instantiate primitive value class`() {
133129
val constructor = BeanUtils.findPrimaryConstructor(PrimitiveValueClass::class.java)!!
134-
assertThat(constructor).isNotNull()
135130
val value = 0
136131
val instance = BeanUtils.instantiateClass(constructor, value)
137132
assertThat(instance).isEqualTo(PrimitiveValueClass(value))
@@ -140,7 +135,6 @@ class BeanUtilsKotlinTests {
140135
@Test
141136
fun `Instantiate class with primitive value class parameter`() {
142137
val constructor = BeanUtils.findPrimaryConstructor(ConstructorWithPrimitiveValueClass::class.java)!!
143-
assertThat(constructor).isNotNull()
144138
val value = PrimitiveValueClass(0)
145139
val instance = BeanUtils.instantiateClass(constructor, value)
146140
assertThat(instance).isEqualTo(ConstructorWithPrimitiveValueClass(value))
@@ -149,14 +143,55 @@ class BeanUtilsKotlinTests {
149143
@Test
150144
fun `Instantiate class with nullable primitive value class parameter`() {
151145
val constructor = BeanUtils.findPrimaryConstructor(ConstructorWithNullablePrimitiveValueClass::class.java)!!
152-
assertThat(constructor).isNotNull()
153146
val value = PrimitiveValueClass(0)
154147
var instance = BeanUtils.instantiateClass(constructor, value)
155148
assertThat(instance).isEqualTo(ConstructorWithNullablePrimitiveValueClass(value))
156149
instance = BeanUtils.instantiateClass(constructor, null)
157150
assertThat(instance).isEqualTo(ConstructorWithNullablePrimitiveValueClass(null))
158151
}
159152

153+
@Test
154+
fun `Get parameter names with Foo`() {
155+
val ctor = BeanUtils.findPrimaryConstructor(Foo::class.java)!!
156+
val names = BeanUtils.getParameterNames(ctor)
157+
assertThat(names).containsExactly("param1", "param2")
158+
}
159+
160+
@Test
161+
fun `Get parameter names filters out DefaultConstructorMarker with ConstructorWithValueClass`() {
162+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithValueClass::class.java)!!
163+
val names = BeanUtils.getParameterNames(ctor)
164+
assertThat(names).containsExactly("value")
165+
}
166+
167+
@Test
168+
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithNullableValueClass`() {
169+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithNullableValueClass::class.java)!!
170+
val names = BeanUtils.getParameterNames(ctor)
171+
assertThat(names).containsExactly("value")
172+
}
173+
174+
@Test
175+
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithPrimitiveValueClass`() {
176+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithPrimitiveValueClass::class.java)!!
177+
val names = BeanUtils.getParameterNames(ctor)
178+
assertThat(names).containsExactly("value")
179+
}
180+
181+
@Test
182+
fun `getParameterNames filters out DefaultConstructorMarker with ConstructorWithNullablePrimitiveValueClass`() {
183+
val ctor = BeanUtils.findPrimaryConstructor(ConstructorWithNullablePrimitiveValueClass::class.java)!!
184+
val names = BeanUtils.getParameterNames(ctor)
185+
assertThat(names).containsExactly("value")
186+
}
187+
188+
@Test
189+
fun `getParameterNames with ClassWithZeroParameterCtor`() {
190+
val ctor = BeanUtils.findPrimaryConstructor(ClassWithZeroParameterCtor::class.java)!!
191+
val names = BeanUtils.getParameterNames(ctor)
192+
assertThat(names).isEmpty()
193+
}
194+
160195

161196
class Foo(val param1: String, val param2: Int)
162197

@@ -216,4 +251,6 @@ class BeanUtilsKotlinTests {
216251

217252
data class ConstructorWithNullablePrimitiveValueClass(val value: PrimitiveValueClass?)
218253

254+
class ClassWithZeroParameterCtor()
255+
219256
}

0 commit comments

Comments
 (0)