21
21
import java .util .Arrays ;
22
22
import java .util .stream .Stream ;
23
23
24
+ import kotlin .jvm .JvmClassMappingKt ;
25
+
24
26
import org .springframework .beans .BeanUtils ;
25
27
import org .springframework .beans .factory .annotation .Autowired ;
26
28
import org .springframework .core .KotlinDetector ;
@@ -41,7 +43,8 @@ class DefaultBindConstructorProvider implements BindConstructorProvider {
41
43
public Constructor <?> getBindConstructor (Bindable <?> bindable , boolean isNestedConstructorBinding ) {
42
44
Constructors constructors = Constructors .getConstructors (bindable .getType ().resolve (),
43
45
isNestedConstructorBinding );
44
- if (constructors .getBind () != null && constructors .isDeducedBindConstructor ()) {
46
+ if (constructors .getBind () != null && constructors .isDeducedBindConstructor ()
47
+ && !constructors .isImmutableType ()) {
45
48
if (bindable .getValue () != null && bindable .getValue ().get () != null ) {
46
49
return null ;
47
50
}
@@ -60,18 +63,22 @@ public Constructor<?> getBindConstructor(Class<?> type, boolean isNestedConstruc
60
63
*/
61
64
static final class Constructors {
62
65
63
- private static final Constructors NONE = new Constructors (false , null , false );
66
+ private static final Constructors NONE = new Constructors (false , null , false , false );
64
67
65
68
private final boolean hasAutowired ;
66
69
67
70
private final Constructor <?> bind ;
68
71
69
72
private final boolean deducedBindConstructor ;
70
73
71
- private Constructors (boolean hasAutowired , Constructor <?> bind , boolean deducedBindConstructor ) {
74
+ private final boolean immutableType ;
75
+
76
+ private Constructors (boolean hasAutowired , Constructor <?> bind , boolean deducedBindConstructor ,
77
+ boolean immutableType ) {
72
78
this .hasAutowired = hasAutowired ;
73
79
this .bind = bind ;
74
80
this .deducedBindConstructor = deducedBindConstructor ;
81
+ this .immutableType = immutableType ;
75
82
}
76
83
77
84
boolean hasAutowired () {
@@ -86,28 +93,34 @@ boolean isDeducedBindConstructor() {
86
93
return this .deducedBindConstructor ;
87
94
}
88
95
96
+ boolean isImmutableType () {
97
+ return this .immutableType ;
98
+ }
99
+
89
100
static Constructors getConstructors (Class <?> type , boolean isNestedConstructorBinding ) {
90
101
if (type == null ) {
91
102
return NONE ;
92
103
}
93
104
boolean hasAutowiredConstructor = isAutowiredPresent (type );
94
105
Constructor <?>[] candidates = getCandidateConstructors (type );
95
106
MergedAnnotations [] candidateAnnotations = getAnnotations (candidates );
107
+ boolean kotlinType = isKotlinType (type );
96
108
boolean deducedBindConstructor = false ;
109
+ boolean immutableType = type .isRecord () || isKotlinDataClass (type );
97
110
Constructor <?> bind = getConstructorBindingAnnotated (type , candidates , candidateAnnotations );
98
111
if (bind == null && !hasAutowiredConstructor ) {
99
112
bind = deduceBindConstructor (type , candidates );
100
113
deducedBindConstructor = bind != null ;
101
114
}
102
- if (bind == null && !hasAutowiredConstructor && isKotlinType ( type ) ) {
115
+ if (bind == null && !hasAutowiredConstructor && kotlinType ) {
103
116
bind = deduceKotlinBindConstructor (type );
104
117
deducedBindConstructor = bind != null ;
105
118
}
106
119
if (bind != null || isNestedConstructorBinding ) {
107
120
Assert .state (!hasAutowiredConstructor ,
108
121
() -> type .getName () + " declares @ConstructorBinding and @Autowired constructor" );
109
122
}
110
- return new Constructors (hasAutowiredConstructor , bind , deducedBindConstructor );
123
+ return new Constructors (hasAutowiredConstructor , bind , deducedBindConstructor , immutableType );
111
124
}
112
125
113
126
private static boolean isAutowiredPresent (Class <?> type ) {
@@ -185,6 +198,10 @@ private static Constructor<?> deduceBindConstructor(Class<?> type, Constructor<?
185
198
return (result != null && result .getParameterCount () > 0 ) ? result : null ;
186
199
}
187
200
201
+ private static boolean isKotlinDataClass (Class <?> type ) {
202
+ return isKotlinType (type ) && JvmClassMappingKt .getKotlinClass (type ).isData ();
203
+ }
204
+
188
205
private static boolean isKotlinType (Class <?> type ) {
189
206
return KotlinDetector .isKotlinPresent () && KotlinDetector .isKotlinType (type );
190
207
}
0 commit comments