From f9d63e7bb1acaa4c752ab73a53513c08e3817021 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 23 Sep 2021 15:53:54 +0200 Subject: [PATCH] BeanUtils.getResolvableConstructor falls back to single non-public constructor Closes gh-27437 --- .../org/springframework/beans/BeanUtils.java | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) 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 8ddd6ff744..f7708247d7 100644 --- a/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/BeanUtils.java @@ -226,32 +226,46 @@ public abstract class BeanUtils { } /** - * Return a resolvable constructor for the provided class, either a primary constructor - * or single public constructor or simply a default constructor. Callers have to be - * prepared to resolve arguments for the returned constructor's parameters, if any. + * Return a resolvable constructor for the provided class, either a primary or single + * public constructor with arguments, or a single non-public constructor with arguments, + * or simply a default constructor. Callers have to be prepared to resolve arguments + * for the returned constructor's parameters, if any. * @param clazz the class to check + * @throws IllegalStateException in case of no unique constructor found at all * @since 5.3 * @see #findPrimaryConstructor */ @SuppressWarnings("unchecked") public static Constructor getResolvableConstructor(Class clazz) { Constructor ctor = findPrimaryConstructor(clazz); - if (ctor == null) { - Constructor[] ctors = clazz.getConstructors(); + if (ctor != null) { + return ctor; + } + + Constructor[] ctors = clazz.getConstructors(); + if (ctors.length == 1) { + // A single public constructor + return (Constructor) ctors[0]; + } + else if (ctors.length == 0){ + ctors = clazz.getDeclaredConstructors(); if (ctors.length == 1) { - ctor = (Constructor) ctors[0]; - } - else { - try { - ctor = clazz.getDeclaredConstructor(); - } - catch (NoSuchMethodException ex) { - throw new IllegalStateException("No primary or single public constructor found for " + - clazz + " - and no default constructor found either"); - } + // A single non-public constructor, e.g. from a non-public record type + return (Constructor) ctors[0]; } } - return ctor; + else { + // Several public constructors -> let's take the default constructor + try { + return clazz.getDeclaredConstructor(); + } + catch (NoSuchMethodException ex) { + // Giving up... + } + } + + // No unique constructor at all + throw new IllegalStateException("No primary or single unique constructor found for " + clazz); } /**