27
27
import org .apache .commons .logging .Log ;
28
28
import org .apache .commons .logging .LogFactory ;
29
29
30
- import org .springframework .beans .factory .NoSuchBeanDefinitionException ;
31
30
import org .springframework .beans .factory .annotation .AnnotatedBeanDefinition ;
32
31
import org .springframework .beans .factory .annotation .AnnotatedGenericBeanDefinition ;
33
32
import org .springframework .beans .factory .annotation .Autowire ;
@@ -119,11 +118,12 @@ public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
119
118
}
120
119
121
120
/**
122
- * Read a particular {@link ConfigurationClass}, registering bean definitions for the
123
- * class itself, all its {@link Bean} methods
121
+ * Read a particular {@link ConfigurationClass}, registering bean definitions
122
+ * for the class itself and all of its {@link Bean} methods.
124
123
*/
125
124
private void loadBeanDefinitionsForConfigurationClass (ConfigurationClass configClass ,
126
125
TrackedConditionEvaluator trackedConditionEvaluator ) {
126
+
127
127
if (trackedConditionEvaluator .shouldSkip (configClass )) {
128
128
removeBeanDefinition (configClass );
129
129
return ;
@@ -140,12 +140,8 @@ private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configC
140
140
}
141
141
142
142
private void removeBeanDefinition (ConfigurationClass configClass ) {
143
- if (StringUtils .hasLength (configClass .getBeanName ())) {
144
- try {
145
- this .registry .removeBeanDefinition (configClass .getBeanName ());
146
- }
147
- catch (NoSuchBeanDefinitionException ex ) {
148
- }
143
+ if (StringUtils .hasLength (configClass .getBeanName ()) && this .registry .containsBeanDefinition (configClass .getBeanName ())) {
144
+ this .registry .removeBeanDefinition (configClass .getBeanName ());
149
145
}
150
146
}
151
147
@@ -196,27 +192,17 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
196
192
beanDef .setAutowireMode (RootBeanDefinition .AUTOWIRE_CONSTRUCTOR );
197
193
beanDef .setAttribute (RequiredAnnotationBeanPostProcessor .SKIP_REQUIRED_CHECK_ATTRIBUTE , Boolean .TRUE );
198
194
199
- // consider name and any aliases
195
+ // Consider name and any aliases
200
196
AnnotationAttributes bean = AnnotationConfigUtils .attributesFor (metadata , Bean .class );
201
197
List <String > names = new ArrayList <String >(Arrays .asList (bean .getStringArray ("name" )));
202
198
String beanName = (names .size () > 0 ? names .remove (0 ) : beanMethod .getMetadata ().getMethodName ());
203
199
for (String alias : names ) {
204
200
this .registry .registerAlias (beanName , alias );
205
201
}
206
202
207
- // has this already been overridden (e.g. via XML)?
208
- if (this .registry .containsBeanDefinition (beanName )) {
209
- BeanDefinition existingBeanDef = registry .getBeanDefinition (beanName );
210
- // is the existing bean definition one that was created from a configuration class?
211
- if (!(existingBeanDef instanceof ConfigurationClassBeanDefinition )) {
212
- // no -> then it's an external override, probably XML
213
- // overriding is legal, return immediately
214
- if (logger .isDebugEnabled ()) {
215
- logger .debug (String .format ("Skipping loading bean definition for %s: a definition for bean " +
216
- "'%s' already exists. This is likely due to an override in XML." , beanMethod , beanName ));
217
- }
218
- return ;
219
- }
203
+ // Has this effectively been overridden before (e.g. via XML)?
204
+ if (isOverriddenByExistingDefinition (beanMethod , beanName )) {
205
+ return ;
220
206
}
221
207
222
208
AnnotationConfigUtils .processCommonDefinitionAnnotations (beanDef , metadata );
@@ -236,7 +222,7 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
236
222
beanDef .setDestroyMethodName (destroyMethodName );
237
223
}
238
224
239
- // consider scoping
225
+ // Consider scoping
240
226
ScopedProxyMode proxyMode = ScopedProxyMode .NO ;
241
227
AnnotationAttributes scope = AnnotationConfigUtils .attributesFor (metadata , Scope .class );
242
228
if (scope != null ) {
@@ -247,7 +233,7 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
247
233
}
248
234
}
249
235
250
- // replace the original bean definition with the target one, if necessary
236
+ // Replace the original bean definition with the target one, if necessary
251
237
BeanDefinition beanDefToRegister = beanDef ;
252
238
if (proxyMode != ScopedProxyMode .NO ) {
253
239
BeanDefinitionHolder proxyDef = ScopedProxyCreator .createScopedProxy (
@@ -257,12 +243,40 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
257
243
}
258
244
259
245
if (logger .isDebugEnabled ()) {
260
- logger .debug (String .format ("Registering bean definition for @Bean method %s.%s()" , configClass .getMetadata ().getClassName (), beanName ));
246
+ logger .debug (String .format ("Registering bean definition for @Bean method %s.%s()" ,
247
+ configClass .getMetadata ().getClassName (), beanName ));
261
248
}
262
249
263
- registry .registerBeanDefinition (beanName , beanDefToRegister );
250
+ this . registry .registerBeanDefinition (beanName , beanDefToRegister );
264
251
}
265
252
253
+ protected boolean isOverriddenByExistingDefinition (BeanMethod beanMethod , String beanName ) {
254
+ if (!this .registry .containsBeanDefinition (beanName )) {
255
+ return false ;
256
+ }
257
+ BeanDefinition existingBeanDef = this .registry .getBeanDefinition (beanName );
258
+
259
+ // Is the existing bean definition one that was created from a configuration class?
260
+ // -> allow the current bean method to override, since both are at second-pass level
261
+ if (existingBeanDef instanceof ConfigurationClassBeanDefinition ) {
262
+ return false ;
263
+ }
264
+
265
+ // Has the existing bean definition bean marked as a framework-generated bean?
266
+ // -> allow the current bean method to override it, since it is application-level
267
+ if (existingBeanDef .getRole () > BeanDefinition .ROLE_APPLICATION ) {
268
+ return false ;
269
+ }
270
+
271
+ // At this point, it's a top-level override (probably XML), just having been parsed
272
+ // before configuration class processing kicks in...
273
+ if (logger .isInfoEnabled ()) {
274
+ logger .info (String .format ("Skipping bean definition for %s: a definition for bean '%s' " +
275
+ "already exists. This top-level bean definition is considered as an override." ,
276
+ beanMethod , beanName ));
277
+ }
278
+ return true ;
279
+ }
266
280
267
281
private void loadBeanDefinitionsFromImportedResources (
268
282
Map <String , Class <? extends BeanDefinitionReader >> importedResources ) {
@@ -294,9 +308,9 @@ private void loadBeanDefinitionsFromImportedResources(
294
308
}
295
309
}
296
310
297
- private void loadBeanDefinitionsFromRegistrars (
298
- AnnotationMetadata importingClassMetadata ,
311
+ private void loadBeanDefinitionsFromRegistrars (AnnotationMetadata importingClassMetadata ,
299
312
Set <ImportBeanDefinitionRegistrar > importBeanDefinitionRegistrars ) {
313
+
300
314
for (ImportBeanDefinitionRegistrar registrar : importBeanDefinitionRegistrars ) {
301
315
registrar .registerBeanDefinitions (importingClassMetadata , this .registry );
302
316
}
0 commit comments