18
18
19
19
import java .beans .PropertyDescriptor ;
20
20
import java .beans .PropertyEditor ;
21
- import java .lang .annotation .Annotation ;
22
21
import java .lang .reflect .Constructor ;
23
22
import java .lang .reflect .InvocationTargetException ;
24
23
import java .lang .reflect .Method ;
42
41
import org .apache .commons .logging .Log ;
43
42
import org .apache .commons .logging .LogFactory ;
44
43
44
+ import org .springframework .core .KotlinDetector ;
45
45
import org .springframework .core .MethodParameter ;
46
46
import org .springframework .lang .Nullable ;
47
47
import org .springframework .util .Assert ;
@@ -70,21 +70,6 @@ public abstract class BeanUtils {
70
70
private static final Set <Class <?>> unknownEditorTypes =
71
71
Collections .newSetFromMap (new ConcurrentReferenceHashMap <>(64 ));
72
72
73
- @ Nullable
74
- private static final Class <?> kotlinMetadata ;
75
-
76
- static {
77
- Class <?> metadata ;
78
- try {
79
- metadata = ClassUtils .forName ("kotlin.Metadata" , BeanUtils .class .getClassLoader ());
80
- }
81
- catch (ClassNotFoundException ex ) {
82
- // Kotlin API not available - no special support for Kotlin class instantiation
83
- metadata = null ;
84
- }
85
- kotlinMetadata = metadata ;
86
- }
87
-
88
73
89
74
/**
90
75
* Convenience method to instantiate a class using its no-arg constructor.
@@ -127,7 +112,7 @@ public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationExc
127
112
throw new BeanInstantiationException (clazz , "Specified class is an interface" );
128
113
}
129
114
try {
130
- Constructor <T > ctor = (useKotlinSupport (clazz ) ?
115
+ Constructor <T > ctor = (KotlinDetector . isKotlinType (clazz ) ?
131
116
KotlinDelegate .findPrimaryConstructor (clazz ) : clazz .getDeclaredConstructor ());
132
117
if (ctor == null ) {
133
118
throw new BeanInstantiationException (clazz , "No default constructor found" );
@@ -174,7 +159,7 @@ public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws
174
159
Assert .notNull (ctor , "Constructor must not be null" );
175
160
try {
176
161
ReflectionUtils .makeAccessible (ctor );
177
- return (useKotlinSupport (ctor .getDeclaringClass ()) ?
162
+ return (KotlinDetector . isKotlinType (ctor .getDeclaringClass ()) ?
178
163
KotlinDelegate .instantiateClass (ctor , args ) : ctor .newInstance (args ));
179
164
}
180
165
catch (InstantiationException ex ) {
@@ -191,6 +176,28 @@ public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws
191
176
}
192
177
}
193
178
179
+ /**
180
+ * Return the primary constructor of the provided class. For Kotlin classes, this
181
+ * returns the Java constructor corresponding to the Kotlin primary constructor
182
+ * (as defined in the Kotlin specification). Otherwise, in particular for non-Kotlin
183
+ * classes, this simply returns {@code null}.
184
+ * @param clazz the class to check
185
+ * @since 5.0
186
+ * @see <a href="http://kotlinlang.org/docs/reference/classes.html#constructors">Kotlin docs</a>
187
+ */
188
+ @ SuppressWarnings ("unchecked" )
189
+ @ Nullable
190
+ public static <T > Constructor <T > findPrimaryConstructor (Class <T > clazz ) {
191
+ Assert .notNull (clazz , "Class must not be null" );
192
+ if (KotlinDetector .isKotlinType (clazz )) {
193
+ Constructor <T > kotlinPrimaryConstructor = KotlinDelegate .findPrimaryConstructor (clazz );
194
+ if (kotlinPrimaryConstructor != null ) {
195
+ return kotlinPrimaryConstructor ;
196
+ }
197
+ }
198
+ return null ;
199
+ }
200
+
194
201
/**
195
202
* Find a method with the given method name and the given parameter types,
196
203
* declared on the given class or one of its superclasses. Prefers public methods,
@@ -331,40 +338,6 @@ else if (!method.isBridge() && targetMethod.getParameterCount() == numParams) {
331
338
return targetMethod ;
332
339
}
333
340
334
- /**
335
- * Return the primary constructor of the provided class. For Java classes, it returns
336
- * the single or the default constructor if any. For Kotlin classes, it returns the Java
337
- * constructor corresponding to the Kotlin primary constructor (as defined in
338
- * Kotlin specification), the single or the default constructor if any.
339
- *
340
- * @param clazz the class to check
341
- * @since 5.0
342
- * @see <a href="http://kotlinlang.org/docs/reference/classes.html#constructors">Kotlin docs</a>
343
- */
344
- @ SuppressWarnings ("unchecked" )
345
- @ Nullable
346
- public static <T > Constructor <T > findPrimaryConstructor (Class <T > clazz ) {
347
- Assert .notNull (clazz , "Class must not be null" );
348
- if (useKotlinSupport (clazz )) {
349
- Constructor <T > kotlinPrimaryConstructor = KotlinDelegate .findPrimaryConstructor (clazz );
350
- if (kotlinPrimaryConstructor != null ) {
351
- return kotlinPrimaryConstructor ;
352
- }
353
- }
354
- Constructor <T >[] ctors = (Constructor <T >[]) clazz .getConstructors ();
355
- if (ctors .length == 1 ) {
356
- return ctors [0 ];
357
- }
358
- else {
359
- try {
360
- return clazz .getDeclaredConstructor ();
361
- }
362
- catch (NoSuchMethodException ex ) {
363
- return null ;
364
- }
365
- }
366
- }
367
-
368
341
/**
369
342
* Parse a method signature in the form {@code methodName[([arg_list])]},
370
343
* where {@code arg_list} is an optional, comma-separated list of fully-qualified
@@ -712,15 +685,6 @@ private static void copyProperties(Object source, Object target, @Nullable Class
712
685
}
713
686
}
714
687
715
- /**
716
- * Return true if Kotlin is present and if the specified class is a Kotlin one.
717
- */
718
- @ SuppressWarnings ("unchecked" )
719
- private static boolean useKotlinSupport (Class <?> clazz ) {
720
- return (kotlinMetadata != null &&
721
- clazz .getDeclaredAnnotation ((Class <? extends Annotation >) kotlinMetadata ) != null );
722
- }
723
-
724
688
725
689
/**
726
690
* Inner class to avoid a hard dependency on Kotlin at runtime.
@@ -736,13 +700,13 @@ private static class KotlinDelegate {
736
700
@ Nullable
737
701
public static <T > Constructor <T > findPrimaryConstructor (Class <T > clazz ) {
738
702
try {
739
- KFunction <T > primaryConstructor = KClasses .getPrimaryConstructor (JvmClassMappingKt .getKotlinClass (clazz ));
740
- if (primaryConstructor == null ) {
703
+ KFunction <T > primaryCtor = KClasses .getPrimaryConstructor (JvmClassMappingKt .getKotlinClass (clazz ));
704
+ if (primaryCtor == null ) {
741
705
return null ;
742
706
}
743
- Constructor <T > constructor = ReflectJvmMapping .getJavaConstructor (primaryConstructor );
707
+ Constructor <T > constructor = ReflectJvmMapping .getJavaConstructor (primaryCtor );
744
708
Assert .notNull (constructor ,
745
- () -> "Failed to find Java constructor corresponding to Kotlin primary constructor: " + clazz .getName ());
709
+ () -> "Failed to find Java constructor for Kotlin primary constructor: " + clazz .getName ());
746
710
return constructor ;
747
711
}
748
712
catch (UnsupportedOperationException ex ) {
@@ -765,9 +729,9 @@ public static <T> T instantiateClass(Constructor<T> ctor, Object... args)
765
729
List <KParameter > parameters = kotlinConstructor .getParameters ();
766
730
Map <KParameter , Object > argParameters = new HashMap <>(parameters .size ());
767
731
Assert .isTrue (args .length <= parameters .size (),
768
- "The number of provided arguments should be less of equals than the number of constructor parameters" );
732
+ "Number of provided arguments should be less of equals than number of constructor parameters" );
769
733
for (int i = 0 ; i < args .length ; i ++) {
770
- if (!(parameters .get (i ).isOptional () && ( args [i ] == null ) )) {
734
+ if (!(parameters .get (i ).isOptional () && args [i ] == null )) {
771
735
argParameters .put (parameters .get (i ), args [i ]);
772
736
}
773
737
}
0 commit comments