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 e80864f5949..c0ab530a40d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java @@ -38,6 +38,7 @@ import kotlin.jvm.JvmClassMappingKt; import kotlin.reflect.KFunction; import kotlin.reflect.KParameter; import kotlin.reflect.full.KClasses; +import kotlin.reflect.jvm.KCallablesJvm; import kotlin.reflect.jvm.ReflectJvmMapping; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -780,6 +781,11 @@ public abstract class BeanUtils { if (kotlinConstructor == null) { return ctor.newInstance(args); } + + if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers()))) { + KCallablesJvm.setAccessible(kotlinConstructor, true); + } + List parameters = kotlinConstructor.getParameters(); Map argParameters = new HashMap<>(parameters.size()); Assert.isTrue(args.length <= parameters.size(), diff --git a/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java b/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java index e03707d9ab6..4510370a3fe 100644 --- a/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/BeanUtilsTests.java @@ -95,6 +95,12 @@ class BeanUtilsTests { BeanUtils.instantiateClass(ctor, null, null, "foo", null)); } + @Test + void testInstantiatePrivateClassWithPrivateConstructor() throws NoSuchMethodException { + Constructor ctor = PrivateBeanWithPrivateConstructor.class.getDeclaredConstructor(); + BeanUtils.instantiateClass(ctor); + } + @Test void testGetPropertyDescriptors() throws Exception { PropertyDescriptor[] actual = Introspector.getBeanInfo(TestBean.class).getPropertyDescriptors(); @@ -555,4 +561,10 @@ class BeanUtilsTests { } } + private static class PrivateBeanWithPrivateConstructor { + + private PrivateBeanWithPrivateConstructor() { + } + } + } diff --git a/spring-beans/src/test/kotlin/org/springframework/beans/KotlinBeanUtilsTests.kt b/spring-beans/src/test/kotlin/org/springframework/beans/KotlinBeanUtilsTests.kt index 948292bd838..647d320fad9 100644 --- a/spring-beans/src/test/kotlin/org/springframework/beans/KotlinBeanUtilsTests.kt +++ b/spring-beans/src/test/kotlin/org/springframework/beans/KotlinBeanUtilsTests.kt @@ -74,6 +74,22 @@ class KotlinBeanUtilsTests { assertThat(baz.param2).isEqualTo(12) } + @Test + @Suppress("UsePropertyAccessSyntax") + fun `Instantiate class with private constructor`() { + BeanUtils.instantiateClass(PrivateConstructor::class.java.getDeclaredConstructor()) + } + + @Test + fun `Instantiate class with protected constructor`() { + BeanUtils.instantiateClass(ProtectedConstructor::class.java.getDeclaredConstructor()) + } + + @Test + fun `Instantiate private class`() { + BeanUtils.instantiateClass(PrivateClass::class.java.getDeclaredConstructor()) + } + class Foo(val param1: String, val param2: Int) class Bar(val param1: String, val param2: Int = 12) @@ -106,4 +122,10 @@ class KotlinBeanUtilsTests { constructor(param1: String) } + class PrivateConstructor private constructor() + + open class ProtectedConstructor protected constructor() + + private class PrivateClass + }