Why does auto-configuration ordering matter, and how does it interact with @ConditionalOnMissingBean?
answer
- Conditions see only already-registered definitions
- First-processed defines the bean, others back off
- Before => win the default; After => fill the gap
- Conditions reliable only on auto-config classes
- Definition/eval order != runtime instantiation order
basics
~10 sOrdering decides which auto-config class is evaluated first. @ConditionalOnMissingBean only sees beans already defined by earlier-processed classes, so the class that runs first defines the bean and later ones back off.
solid answer
~40 sAuto-config ordering matters because bean-presence conditions are evaluated against the beans defined so far. @ConditionalOnBean and @ConditionalOnMissingBean don't see the whole context at once — they inspect only definitions registered by auto-configurations processed before the current one. So if two classes both offer a DataSource guarded by @ConditionalOnMissingBean, whichever is processed first defines it and the other backs off. That's why Spring's docs say these conditions are reliable only inside auto-config classes with correct @AutoConfigureBefore/@AutoConfigureAfter ordering, and are fragile on user @Configuration. Ordering changes definition/evaluation order, not runtime instantiation order — that stays dependency-driven. To make your bean the winning default, run before the framework class; to only fill a gap, run after it and use @ConditionalOnMissingBean.
code
java · 16 lines// My library wants its DataSource to WIN over Spring Boot's default.
// Processing before the framework class means mine is defined first;
// the framework's @ConditionalOnMissingBean then backs off.
@AutoConfiguration(before = DataSourceAutoConfiguration.class)
public class MyDataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean(DataSource.class)
DataSource dataSource() {
return buildCustomPooledDataSource();
}
}
// If instead I only want to provide a fallback when nobody else did,
// I run AFTER and rely on @ConditionalOnMissingBean to fill the gap:
// @AutoConfiguration(after = DataSourceAutoConfiguration.class)go deeper
May not connect ordering to conditions at all.
Should know first-processed-wins for @ConditionalOnMissingBean.
Should explain the definition-visibility mechanism and the before-to-win / after-to-defer pattern.
Should design starter override strategies and warn about the instantiation-vs-definition-order trap and user-@Configuration unreliability.
**The core coupling.** `@ConditionalOnBean` and `@ConditionalOnMissingBean` are evaluated as the container processes configuration classes. Crucially, they can only observe bean **definitions that have already been registered** at the moment the condition is checked. Auto-configuration runs *after* user configuration and in a **sorted, deterministic order**, so within the auto-config phase the presence checks are well-defined — but only if ordering is correct. **The classic scenario.** Suppose `FrameworkAutoConfiguration` defines a `DataSource` with `@ConditionalOnMissingBean(DataSource.class)`, and your library's `MyAutoConfiguration` also defines one with the same guard. - If your class is processed **before** the framework's, yours defines the `DataSource`; the framework's condition then sees it and backs off — your bean wins. - If processed **after**, the framework defines it first and yours backs off. You pick the outcome with `@AutoConfigureBefore(FrameworkAutoConfiguration.class)` (to win) or `@AutoConfigureAfter(...)` (to defer to it and only fill a gap). **Why user @Configuration is different.** The Spring Boot reference explicitly warns that `@ConditionalOnBean`/`@ConditionalOnMissingBean` should generally be used **only on auto-configuration classes**, because user `@Configuration` classes are processed in a phase where global bean visibility is not guaranteed, making presence checks order-sensitive and unreliable. Ordering annotations don't help there because they are honored only for auto-config classes. **Definition order vs instantiation order.** A frequent confusion: ordering controls the sequence in which configuration classes are *evaluated and bean definitions registered*, and therefore which conditions fire. It does **not** dictate the order beans are *instantiated at runtime* — that is determined by the dependency graph (a bean is created when something needs it, respecting `@DependsOn` and constructor injection). So `@AutoConfigureBefore` is about 'who defines what first', not 'who is constructed first'. **Edge cases / gotchas.** - Ordering does not create dependencies. If bean B needs bean A at runtime, express that via injection or `@DependsOn`; `@AutoConfigureAfter` alone won't guarantee A is instantiated first. - `@ConditionalOnMissingBean` without a type sometimes infers from the `@Bean` return type; combined with ordering surprises, this is a common source of 'my bean didn't win' bugs. - A `@ConditionalOnBean` in an earlier-processed class referencing a bean defined by a *later* class will evaluate as absent — order the referencing class *after* the defining one. **When to use.** Whenever you ship a starter that must override, extend, or defer to a framework default. Get the before/after relationship right, then let conditions do the back-off.
- Does @AutoConfigureAfter(A) guarantee that bean A is instantiated before my bean at runtime?No. It only guarantees A's configuration class is processed (definitions registered, conditions evaluated) before yours. Runtime instantiation order follows the dependency graph; use constructor injection or @DependsOn for that.
- Why does Spring warn against @ConditionalOnMissingBean on user @Configuration classes?User @Configuration is processed in a phase without guaranteed global bean visibility, so the presence check is order-sensitive and unreliable. These conditions are designed for the deterministically-ordered auto-configuration phase.
saying these in an interview costs you the question
- Saying ordering controls runtime bean instantiation order
- Assuming @ConditionalOnMissingBean sees the fully-populated context regardless of order
- Using @ConditionalOnBean/@ConditionalOnMissingBean freely on user @Configuration and expecting deterministic results