@@ -104,6 +104,21 @@ public DefaultBinderFactory(Map<String, BinderConfiguration> binderConfiguration
104
104
this .binderCustomizer = binderCustomizer ;
105
105
}
106
106
107
+ /**
108
+ * Replaces the existing binder configurations - useful in AOT processing where the binding service properties
109
+ * have to be manually loaded after the binder factory is constructed.
110
+ *
111
+ * @param binderConfigurations the updated configurations
112
+ */
113
+ void updateBinderConfigurations (Map <String , BinderConfiguration > binderConfigurations ) {
114
+ this .binderConfigurations .clear ();
115
+ this .binderConfigurations .putAll (binderConfigurations );
116
+ }
117
+
118
+ BinderTypeRegistry getBinderTypeRegistry () {
119
+ return this .binderTypeRegistry ;
120
+ }
121
+
107
122
@ Override
108
123
public void setApplicationContext (ApplicationContext applicationContext ) {
109
124
Assert .isInstanceOf (ConfigurableApplicationContext .class , applicationContext );
@@ -126,17 +141,14 @@ public void destroy() {
126
141
127
142
@ SuppressWarnings ({ "unchecked" , "rawtypes" })
128
143
@ Override
129
- public synchronized <T > Binder <T , ?, ?> getBinder (String name ,
130
- Class <? extends T > bindingTargetType ) {
131
144
145
+ public synchronized <T > Binder <T , ?, ?> getBinder (String name , Class <? extends T > bindingTargetType ) {
132
146
String binderName = StringUtils .hasText (name ) ? name : this .defaultBinder ;
133
147
134
- Map <String , Binder > binders = this .context == null ? Collections .emptyMap ()
135
- : this .context .getBeansOfType (Binder .class );
148
+ Map <String , Binder > binders = this .context == null ? Collections .emptyMap () : this .context .getBeansOfType (Binder .class );
136
149
Binder <T , ConsumerProperties , ProducerProperties > binder ;
137
150
if (StringUtils .hasText (binderName ) && binders .containsKey (binderName )) {
138
- binder = (Binder <T , ConsumerProperties , ProducerProperties >) this .context
139
- .getBean (binderName );
151
+ binder = (Binder <T , ConsumerProperties , ProducerProperties >) this .context .getBean (binderName );
140
152
}
141
153
else if (binders .size () == 1 ) {
142
154
binder = binders .values ().iterator ().next ();
@@ -149,7 +161,7 @@ else if (binders.size() > 1) {
149
161
}
150
162
else {
151
163
/*
152
- * This is the fall back to the old bootstrap that relies on spring.binders.
164
+ * This is the fallback to the old bootstrap that relies on spring.binders.
153
165
*/
154
166
binder = this .doGetBinder (binderName , bindingTargetType );
155
167
}
@@ -160,27 +172,37 @@ else if (binders.size() > 1) {
160
172
}
161
173
162
174
private <T > Binder <T , ConsumerProperties , ProducerProperties > doGetBinder (String name , Class <? extends T > bindingTargetType ) {
163
- if (CollectionUtils .isEmpty (this .binderChildContextInitializers )) {
164
- return this .doGetBinderConventional (name , bindingTargetType );
175
+ // If child initializers - use AOT lookup
176
+ if (!CollectionUtils .isEmpty (this .binderChildContextInitializers )) {
177
+ return this .doGetBinderAOT (name , bindingTargetType );
165
178
}
166
- else {
167
- if ((!StringUtils .hasText (name ) || this .defaultBinder != null ) && this .binderChildContextInitializers .size () == 1 ) {
179
+ return this .doGetBinderConventional (name , bindingTargetType );
180
+ }
181
+
182
+ private <T > Binder <T , ConsumerProperties , ProducerProperties > doGetBinderAOT (String name , Class <? extends T > bindingTargetType ) {
183
+ // If neither name nor default given - return single or fail when > 1
184
+ if (!StringUtils .hasText (name ) && !StringUtils .hasText (this .defaultBinder )) {
185
+ if (this .binderChildContextInitializers .size () == 1 ) {
168
186
String configurationName = this .binderChildContextInitializers .keySet ().iterator ().next ();
187
+ this .logger .debug ("No specific name or default given - using single available child initializer '" + configurationName + "'" );
169
188
return this .getBinderInstance (configurationName );
170
189
}
171
- else if ( this . defaultBinder != null && this . binderChildContextInitializers . size () > 1 ) {
172
- // Handling default binder when different binders are present on the classpath.
173
- for ( String binderName : this . binderChildContextInitializers . keySet ()) {
174
- if ( binderName . equals ( this . defaultBinder )) {
175
- return this . getBinderInstance ( binderName ) ;
176
- }
177
- }
178
- throw new IllegalStateException ( "Default binder provided, but can't determine which binder to initialize" );
179
- }
180
- else {
181
- throw new IllegalStateException ( "Can't determine which binder to use: " + name + "/" + this .binderChildContextInitializers .size ());
182
- }
190
+ throw new IllegalStateException ( "No specific name or default given - can't determine which binder to use" );
191
+ }
192
+
193
+ // Prefer specific name over default
194
+ String configurationName = name ;
195
+ if (! StringUtils . hasText ( configurationName )) {
196
+ configurationName = this . defaultBinder ;
197
+ }
198
+
199
+ // Check for matching child initializer
200
+ if ( this .binderChildContextInitializers .containsKey ( configurationName )) {
201
+ return this . getBinderInstance ( configurationName );
183
202
}
203
+
204
+ throw new IllegalStateException ("Requested binder '" + name + "' did not match available binders: " +
205
+ this .binderChildContextInitializers .keySet ());
184
206
}
185
207
186
208
private <T > Binder <T , ConsumerProperties , ProducerProperties > doGetBinderConventional (String name ,
@@ -296,16 +318,19 @@ private <T> Binder<T, ConsumerProperties, ProducerProperties> getBinderInstance(
296
318
ConfigurableApplicationContext binderProducingContext ;
297
319
if (this .binderChildContextInitializers .containsKey (configurationName )) {
298
320
this .logger .info ("Using AOT pre-prepared initializer to construct binder child context for " + configurationName );
321
+ if (binderConfiguration != null ) {
322
+ this .flatten (null , binderConfiguration .getProperties (), binderProperties );
323
+ }
299
324
binderProducingContext = this .createUnitializedContextForAOT (configurationName , binderProperties , binderConfiguration );
300
325
this .binderChildContextInitializers .get (configurationName ).initialize (binderProducingContext );
301
326
binderProducingContext .refresh ();
302
327
}
303
328
else {
329
+ this .logger .info ("Constructing binder child context for " + configurationName );
304
330
Assert .state (binderConfiguration != null , "Unknown binder configuration: " + configurationName );
331
+ this .flatten (null , binderConfiguration .getProperties (), binderProperties );
305
332
BinderType binderType = this .binderTypeRegistry .get (binderConfiguration .getBinderType ());
306
333
Assert .notNull (binderType , "Binder type " + binderConfiguration .getBinderType () + " is not defined" );
307
- this .flatten (null , binderConfiguration .getProperties (), binderProperties );
308
- this .logger .info ("Constructing binder child context for " + configurationName );
309
334
binderProducingContext = this .initializeBinderContextSimple (configurationName , binderProperties ,
310
335
binderType , binderConfiguration , true );
311
336
}
0 commit comments