Skip to content

Commit d777b70

Browse files
committed
Ignore DefaultConstructorMarker in BeanUtils#getParameterNames
Closes gh-34760
1 parent 472c401 commit d777b70

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 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.
@@ -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;
@@ -669,7 +670,9 @@ public static String[] getParameterNames(Constructor<?> ctor) {
669670
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
670671
String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
671672
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
672-
Assert.state(paramNames.length == ctor.getParameterCount(),
673+
int parameterCount = (KotlinDetector.isKotlinReflectPresent() && KotlinDelegate.hasDefaultConstructorMarker(ctor) ?
674+
ctor.getParameterCount() - 1 : ctor.getParameterCount());
675+
Assert.state(paramNames.length == parameterCount,
673676
() -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor);
674677
return paramNames;
675678
}
@@ -939,6 +942,11 @@ public static <T> T instantiateClass(Constructor<T> ctor, Object... args)
939942
}
940943
return kotlinConstructor.callBy(argParameters);
941944
}
945+
946+
public static boolean hasDefaultConstructorMarker(Constructor<?> ctor) {
947+
int parameterCount = ctor.getParameterCount();
948+
return parameterCount > 0 && ctor.getParameters()[parameterCount -1].getType() == DefaultConstructorMarker.class;
949+
}
942950
}
943951

944952
}

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

Lines changed: 45 additions & 1 deletion
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.
@@ -157,6 +157,48 @@ class BeanUtilsKotlinTests {
157157
assertThat(instance).isEqualTo(ConstructorWithNullablePrimitiveValueClass(null))
158158
}
159159

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

161203
class Foo(val param1: String, val param2: Int)
162204

@@ -216,4 +258,6 @@ class BeanUtilsKotlinTests {
216258

217259
data class ConstructorWithNullablePrimitiveValueClass(val value: PrimitiveValueClass?)
218260

261+
class ClassWithZeroParameterCtor()
262+
219263
}

0 commit comments

Comments
 (0)