Skip to content

Allow bean definitions from @Configuration classes to override those defined in XML [SPR-7341] #12000

Closed
@spring-projects-issues

Description

@spring-projects-issues

Eric Sirianni opened SPR-7341 and commented

The ConfigurationClassBeanDefinitionReader hardcodes the behavior that bean definitions from XML always override bean definitions from JavaConfig classes:

// has this already been overridden (e.g. via XML)?
if (this.registry.containsBeanDefinition(beanName)) {
     BeanDefinition existingBeanDef = registry.getBeanDefinition(beanName);
     // is the existing bean definition one that was created from a configuration class?
     if (!(existingBeanDef instanceof ConfigurationClassBeanDefinition)) {
          // no -> then it's an external override, probably XML
          // overriding is legal, return immediately
          if (logger.isDebugEnabled()) {
                   logger.debug(String.format("Skipping loading bean definition for %s: a definition for bean " +
                                     "'%s' already exists. This is likely due to an override in XML.", method, beanName));
          }
          return;
     }
}

I don't see why this decision was made. The normal semantics of using the order in which bean definitions were registered would seem to make sense to apply here as well.

For example:

@Configuration
@ImportResource("foo.xml")
class FooConfig {
  @Bean bean1() { ... }
}

@Configuration
@ImportResource("bar.xml")
class BarConfig {
  @Bean bean1() { ... }
  @Bean bean2() { ... }
}

...
new AnnotationConfigApplicationContext(FooConfig.class, BarConfig.class)

I would expect the following override order to apply:

  1. beans defined in foo.xml
  2. overridden by beans defined in FooConfig
  3. overridden by beans defined in bar.xml
  4. overridden by beans defined in BarConfig

Instead it appears the override order is:

  1. beans defined in FooConfig
  2. overridden by beans defined in BarConfig
  3. overridden by beans defined in foo.xml
  4. overridden by beans defined in bar.xml

This is not intuitive. Specifically, note the interleaving of beans between both Foo and Bar configurations. The clients who use FooConfig and BarConfig don't care whether the beans defined by those Configuration classes come from XML or java. Yet, the override ordering forces them to be aware of this implementation detail.

I realize changing the behavior outright might present a backwards compatibility issue, so is it possible to add a boolean option to the ApplicationContext to respect the registration ordering regardless of whether the bean definition comes from XML or JavaConfig?


Affects: 3.0.3

Issue Links:

24 votes, 21 watchers

Metadata

Metadata

Assignees

Labels

has: votes-jiraIssues migrated from JIRA with more than 10 votes at the time of importin: coreIssues in core modules (aop, beans, core, context, expression)status: declinedA suggestion or change that we don't feel we should currently applytype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions